我如何定位被点击的 React 组件

Posted

技术标签:

【中文标题】我如何定位被点击的 React 组件【英文标题】:How do i target React component which is clicked 【发布时间】:2021-05-17 14:22:31 【问题描述】:

我想在单击时更改组件的类。我使用状态创建一个具有 name 和 done 属性的新组件(创建时为 false)。然后将其推送到 todos 数组中。 现在的问题是如何找到单击了哪个组件并将其“完成”属性更改为 !done ?

function App() 
    const [todos, setTodos] = useState([])
    const [newTodo, setNewTodo] = useState(
        name: "",
        done: false
    )

    const handleInput = (event) => 
        setNewTodo(name: event.target.value)
    

    const handleDone = (event) => 

        //WHAT TO DO HERE

    
    


    const submitTodo = (event) => 
        event.preventDefault();
        setTodos([...todos, newTodo.name])
        console.log(newTodo.name)
        setNewTodo(name: "")
    

  return (
    <div className="App">
        <form onSubmit=submitTodo>
            <input onChange=handleInput value=newTodo.name/>
            <button>Add Todo!</button>
        </form>


        <ul>
            todos.map(todo => (
                <li className=/*Change the class based on the DONE property*/ onClick=handleDone>todo</li>
            ))
        </ul>

    </div>
  );


export default App;

【问题讨论】:

我认为你应该使用 onClick=() => handleDone(todo) 然后 todo 应该在你的handleDone方法的事件参数中(但不确定,因为我没有做过任何反应了很长一段时间) 【参考方案1】:

首先,您应该始终让您的待办事项同时包含namedone 属性。有了这个,您只需将待办事项从点击的&lt;li&gt; 传递给您的点击处理程序,这样它就可以修改其完成属性并通过更新todos 状态来重新渲染。

function App() 
    const [todos, setTodos] = useState([])
    const [newTodo, setNewTodo] = useState(
        name: "",
        done: false
    )

    const handleInput = (event) => 
        setNewTodo(name: event.target.value, done: false ); // this now adds done property
    

    const handleDone = (todo) => 
        todo.done = !todo.done;
        setTodos([...todos]); // This sets new todos to cause a rerender with updated list
    
    
    const submitTodo = (event) => 
        event.preventDefault();
        setTodos([...todos, newTodo]) // this now appends entire newTodo item not only it's name
        setNewTodo(name: "", done: false) // this now also sets default done
    

  return (
    <div className="App">
        <form onSubmit=submitTodo>
            <input onChange=handleInput value=newTodo.name/>
            <button>Add Todo!</button>
        </form>

        <ul>
            todos.map(todo => (
                <li
                    className=todo.done ? 'classA' : 'classB'
                    onClick=() => handleDone(todo)
                >
                    todo.name // this now displays todo.name not todo
                </li>
            ))
        </ul>

    </div>
  );


export default App;

此外,您可以将待办事项和点击处理程序提取到单独的组件中:

function ToDo( item ) 
   const [clicked, setClicked] = useState(item.done);

   const handleClick = useCallback(() => 
       item.done = !clicked
       setClicked(!clicked);
   , [clicked]);

   return <li
       className=clicked ? 'classA' : 'classB'
       onClick=handleClick
   >
       item.name
    </li>;

然后用你的 App 组件渲染一个组件列表:

<ul>
    todos.map(todo => <ToDo item=todo />
</ul>

【讨论】:

这解决了它。是的,我创建了“完成”属性,但我的 todos 在推送到 todos 或函数中时不包含它。谢谢。【参考方案2】:

改变你的 newTodo 状态

const [newTodo, setNewTodo] = useState('');
const [show,setShow] = useState(false);


const handleDone = (event) => setShow(!show)

.....
.....
.....

<li className=show ? 'classname when show is true': 'classname when show is false' onClick=handleDone>todo</li>


【讨论】:

简单,但它仍然不针对特定的待办事项。单击一个后,所有类别都会更改。但仍然感谢您的贡献。

以上是关于我如何定位被点击的 React 组件的主要内容,如果未能解决你的问题,请参考以下文章

react用了固定定位之后子组件不能滚动了

React-bootstrap NavBar 和组件定位使用 css 问题

React.js:如何在点击时附加组件?

React Renders 在我的组件底部!没有顶部

[react] 在React中如何判断点击元素属于哪一个组件?

手写react优惠券组件