如何使按钮适用于单击的确切元素而不是渲染列表中的所有元素

How to make button work for the exact element clicked on rather than all element on rendered list

所以我有一个从数组创建的呈现列表,列表中的每个元素都有一个菜单按钮,它显示每个元素的模式,现在问题是如果我单击索引 0 的按钮而不是仅显示索引 0 它显示所有其他索引

import React, {useState} from 'react'
import ListModal from './listModal';


export const Todo = ({ Todos, deleteItem }) => {
    const [show, setshow] = useState(false);
    const unshow = () => {
        setshow(current => !current)
    }
    return (
        <ul>
            {
                Todos.map((item, index) => (
                    <li key={index}>
                        <button className="deleteBoard" onClick={unshow}>•••</button>
                        <span>{item}</span>
                        <ListModal value = {item} show={show} unshow = {unshow} />
                    </li>
                ))
            }
        </ul>
    );
};

ListModal 设置为显示:"none" 所以当我单击按钮时它显示列表模式,反之亦然

import React, { useState } from 'react'
import firebase from 'firebase/app';
import { db } from '../Firebase/Firebase';
import { useRouteMatch } from 'react-router-dom';


const ListModal = ({ value, show, unshow }) => {
    const [text, settext] = useState(value)
    const styles = {
        display: show ? 'flex' : 'none'
    }
    const textChange = (e) => {
        settext(e.target.value)
    }
    return (
        <div className="listModal" style={styles}>
            <div className="listContent">
                <textarea value={text} rows="6" onChange={textChange}></textarea>
                <button>Save</button>
                <button onClick={unshow}>Cancel</button>
            </div>
            <div className="listOption">
                <ul>
                    <li onClick={() => {deleteItem(value);moveCard()}}>Delete</li>
                </ul>
            </div>

        </div>
    )
}
export default ListModal

提前致谢,我不介意重写请帮帮我。谢谢

在父组件中我设置了模式并传入值

Todos.map((item, index) => (
                    <li key={index}>
                        <ListModal value={item}/>
                    </li>
                ))

然后在子组件中设置打开和关闭功能

const [show, setshow] = useState(false);

const styles = {
        display: show ? 'flex' : 'none'
    }
   
    const isOpen = () => {
        setshow(show => !show);
    }

之后,您可以在子组件中使用 onclick 呈现项目信息和按钮

//Whatever stuff you want to render from the passed in data


return (
        <span>{value}</span>
        <button onClick={() => {() => isOpen()}}>View</button>

        <div className="listModal" style={styles}>
            <div className="listContent">
                <textarea value={text} rows="6" onChange={textChange}></textarea>
                <button>Save</button>
                <button onClick={unshow}>Cancel</button>
            </div>
            <div className="listOption">
                <ul>
                    <li onClick={() => {deleteItem(value);moveCard()}}>Delete</li>
                </ul>
            </div>

        </div>
    )


我建议您采用以下仍可进一步改进的方法:

  • 代替unshow方法,创建两个方法showModalhideModal
    const showModal = (item) => {
      setSelectedTodo(item);
      setshow(true);
    }
    const hideModal = () => {
      setSelectedTodo('');
      setshow(false);
    }
  • 为选定的 Todo 使用另一个 useState
    const [selectedTodo, setSelectedTodo] = useState('')
  • 列表后只有一个 ListModal 实例,它从 state
  • 获取项目
    ...
    <ul>
    {
      Todos.map((item, index) => (
        ...
      ))
    }
    </ul>
    <ListModal value={selectedTodo} show={show} unshow = {hideModal} />
    ...
  • 点击任何按钮,将当前待办事项传递给 showModal 方法

    <button className="deleteBoard" onClick={()=> showModal(item)}>•••</button>

我不需要更改我的 listModal 组件中的任何内容。这是我做了一些更改的父组件

import React, { useState } from 'react'
import ListModal from './listModal';

export const Todo = ({ Todos, deleteItem }) => {
    const [show, setshow] = useState(false);
    const [selected, setselected] = useState("")
    const toggle = () => {
        setshow(show => !show)
    }
    const select = (item) => {
        setselected(item)
    }
    return (
        <>
            <ul>
                {
                    Todos.map((item, index) => (
                        <li key={index}>
                            <button className="deleteBoard" onClick={() => { toggle(); select(item) }}>•••</button>
                            <span>{item}</span>
                        </li>
                    ))
                }
            </ul>
            <ListModal val={selected}  deleteItem={deleteItem} show={show} toggle={toggle} />
        </>
    );
};

说明:: 而不是将 listModal 放在 map 方法中,从而为列表中呈现的每个元素创建一个 listModal 组件。我将它保留在 map 方法之外,因此对于 map 方法中的每个元素,我只有一个 listModal 组件。所有更改都是 listModal 显示的值。

我还创建了一个方法 select,该方法采用参数(项目),即显示的值并将其存储在 selected 中。 selected 是一个状态,然后我将 selected 传递给 listModal。

这就是我所做的一切,如果我的解释不当,请见谅。