javascript - React Hooks 的奇怪 'id' 和复选框行为

标签 javascript reactjs react-hooks

我正在使用 React Hooks 构建一个简单的“待办事项列表”。现在我遇到两个问题:

1) 前两个列表项具有相同的“id”值(即使我递增计数器...) enter image description here

2) 仅在双击后才会选中并更新复选框

我将感谢您的提示、线索、评论、建议和解决方案! :-)

这是“ToDoList”组件:

import React, { useState, useEffect } from 'react';
import ListItem from './ToDoItem';

const ToDoList = () => {
let [counter, setCounter] = useState(1);
let initialItem = {
    id: counter,
    name: '',
    time: '',
    finished: false,
}

const [tasks, setTasks] = useState([]);
useEffect(() => console.log('THE ARRAY OF TASKS', tasks), [tasks]);

const [task, setTask] = useState(initialItem);

const handleSubmit = (e) => {
    e.preventDefault();
    setCounter(counter + 1);
    setTask(prevState => {
        return { ...prevState, id: counter}
    });
    setTasks([...tasks, task]);
    setTask(initialItem);
}

const deleteItem = (id) => {
    let newTasks = tasks.filter((item, index) => {
        return index !== id
    });
    setTasks(newTasks);
}

const handleCheckbox = (val, id) => {
    tasks.map((element) => {
        if (element.id === id) {
            element.finished = val
        }
    })
    console.log('UPDATED TASKS', tasks)
}

return (
    <div>
        <form onSubmit={handleSubmit}>
            <input placeholder="Add a task" value={task.name} onChange={(e) => {
                let value = e.target.value;
                setTask(prevState => {
                    return { ...prevState, name: value }
                })
            }}></input>

            <input placeholder="Add time" value={task.time} onChange={(e) => {
                let value = e.target.value;
                setTask(prevState => {
                    return { ...prevState, time: value }
                })
            }}></input>
            <button>Submit</button>
        </form>
        <ListItem tasks={tasks} delete={deleteItem} checked={handleCheckbox} />
    </div>
)
}

export default ToDoList;

这是“ListItem”组件:

import React, { useState } from 'react';


function ListItem(props) {
    const tasks = props.tasks;
    const [isChecked, setIsChecked] = useState(false);

    return tasks.map((element, index) => {
        return <li key={index}>
            {element.name}: {element.time}
            <button onClick={() => props.delete(index)}>delete</button>
            <label className="container">
                <input type="checkbox" checked={element.finished}
                    onChange={(e) => setIsChecked(!isChecked)} 
                    onClick={(e) => {props.checked(isChecked, element.id);}}>
                </input>
                <span className="checkmark"></span>
            </label>
        </li>
    })
}

export default ListItem;

最佳答案

状态 setter 是异步的,这意味着 setCounter 之后的行可能会在计数器的值实际更新之前运行。

在您的情况下,您更新计数器的唯一时间似乎是在添加新任务之前,因此您可以重构代码,以便在计数器更改时添加任务发生效果:

const handleSubmit = (e) => {
    e.preventDefault();
    setCounter(count => count + 1);
};
useEffect(() => {
    setTask(prevState => {
        return { ...prevState, id: counter}
    });
    setTasks([...tasks, task]);
    setTask(initialItem);
}, [counter]);

尽管现在,当 setTask 尚未完成时,您可能会遇到与使用任务相同的问题。但是,您可能不需要设置任务,使用任务,然后重置任务都处于这样的状态。试试这个:

const handleSubmit = (e) => {
    e.preventDefault();
    setCounter(count => count + 1);
};
useEffect(() => {
    const newTask = {...task, id: counter};
    setTasks([...tasks, task]);
    setTask(initialItem);
}, [counter]);

这样,代码就不必等待任务状态更新,并且不会出现竞争条件。 (这假设“任务”在提交之前不太可能立即更改,因此在创建新对象时仅提取“任务”的当前值是安全的。)

关于javascript - React Hooks 的奇怪 'id' 和复选框行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59165126/

相关文章:

javascript - Bootstrap 3 : popover does not appear initially when initiated by click event of a class

javascript - 如何将 Tic Tac Toe 函数 "Chose function"组合在一个函数中并选择单元格而不是隐藏?

javascript - 对样式化组件使用自定义文档时未传递 Prop

reactjs - 将类组件转换为功能组件

javascript - onclick 单选按钮将数字添加到总数中,但无限添加

reactjs - 如何在 enzyme 测试用例中模拟拖放?

javascript - 每次状态改变时如何在 ReactJS 中重做 API 调用?

reactjs - 在 useEffect 之外设置已卸载组件的状态

javascript - React 中动态加载的 CSS 无法间歇性工作

javascript - 数组被覆盖