繁体   English   中英

反应钩子更新数组不起作用

[英]React hooks updating array is not working

我目前正在学习钩子,我正在写一个待办事项列表:

import './App.css';
import React, {useState} from 'react';
import Item from './components/Item';
function App() {
  const [tasks, setTasks] = useState([]);

  const addTask = (e) => {
    if(e.key === 'Enter'){
      let newTask = {content: e.target.value, completed: false};
      console.log(newTask);
      setTasks(prevTask => {
        return ([...prevTask, newTask]);
      });  
      console.log(tasks);
    }
  }

  const completeTask = (e) =>{
    let newTask = tasks.slice();
    newTask[e].completed = !tasks[e].completed;
    setTasks(newTask);
  }

  const deleteTask = (e) => {
    let newTask = tasks.slice();
    newTask.splice(e);
    setTasks(newTask);
  }

  return (
    <>
      <header className="todo-app__header">
        <h1 className="todo-app__title">todos</h1>
      </header>
      <section className="todo-app__main">
        <input className="todo-app__input" placeholder="What needs to be done?" onKeyDown={addTask}/>
        <ul className="todo-app__list" id="todo-list">
          {tasks.map(item => <Item num = {tasks.indexOf(item)} text={item.content} completed = {item.completed} 
          onClick = {completeTask(tasks.indexOf(item))} delete = {deleteTask(tasks.indexOf(item))}/>)}
        </ul>
      </section>
    </>
  );
}

export default App;

但是,添加任务不起作用!! 打印的 newTask 很好,但它没有推入任务数组。 任务还是空的。

有什么问题? 另外,另一个问题:它与useeffect相关吗? 我不知道useeffect是做什么用的。

问题是每次您的组件渲染时,它都会执行completeTaskdeleteTask ,因为您使用函数调用作为道具。 您需要传入一个函数对象或表达式。 不是告诉组件在单击时执行completeTask ,函数调用只是在组件呈现后立即执行它。

问题在于您的代码的这一部分:

<ul className="todo-app__list" id="todo-list">
    {tasks.map(item => <Item num = {tasks.indexOf(item)} text={item.content} completed = {item.completed} 
    onClick = {completeTask(tasks.indexOf(item))} delete = {deleteTask(tasks.indexOf(item))}/>)}
 </ul>

以下几行:

delete = {deleteTask(tasks.indexOf(item))}
onClick = {completeTask(tasks.indexOf(item))}

应改为:

delete = {() => deleteTask(tasks.indexOf(item))}
onClick = {() => completeTask(tasks.indexOf(item))}

在普通 HTML 中,它看起来像delete="deleteFunction()" ,但在 React 中,它应该是delete={deleteFunction} ,因为在它之后写一个带括号的函数是一个函数调用,而不是一个函数表达式 如果需要传入参数,可以将参数作为组件的 prop 传入,或者将行更改为delete={() => deleteFunction(arg)} ,因为括号和箭头使其成为函数表达。

请参阅处理事件: https : //reactjs.org/docs/handling-events.html

您的代码运行良好,没有问题。

异步反应setState动作。 尝试将其记录在useEffect

const App = () = => {
    const [tasks, setTasks] = useState([]);

    useEffect(() => {
        console.log(tasks)
    }, [tasks]);

    const addTask = () => {
        const newTask = {...};
        setTasks([...tasks, newTask]);
    }
}

使用效果文档

正如我所看到的,您在同一个函数中执行console.log(tasks) 在函数外部尝试console.log(tasks) ,您将看到带有您输入的值的tasks数组。

没有问题

    import React, {useState} from 'react';
function Add() {
    const [tasks, setTasks] = useState([]);
    const addTask = (e) => {
        if(e.key === 'Enter'){
            let newTask = {content: e.target.value, completed: false};
            console.log(newTask);
            setTasks(prevTask => {
               return ([...prevTask, newTask])
            });
            console.log(tasks);
        }
    }

    const completeTask = (e) =>{
        let newTask = tasks.slice();
        newTask[e].completed = !tasks[e].completed;
        setTasks(newTask);
    }

    const deleteTask = (e) => {
        let newTask = tasks.slice();
        newTask.splice(e);
        setTasks(newTask);
    }

    return (
        <>
            <header className="todo-app__header">
                <h1 className="todo-app__title">todos</h1>
            </header>
            <section className="todo-app__main">
                <input className="todo-app__input" placeholder="What needs to be done?" onKeyDown={addTask}/>
                <ul className="todo-app__list" id="todo-list">
                    {tasks.map((item)=> <li>{item.content}</li>)}
                </ul>
            </section>
        </>
    );
}

export default Add;

它运行良好,这意味着您的 Item 组件是您的问题。

尝试改变:

 setTasks(prevTask => { return ([...prevTask, newTask]); });

setTasks(prevTask => [...prevTask, newTask]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM