【问题标题】:React input saves the input at first click then shows it in the UI on second click... WHY ?!!! and how to fix itReact 输入会在第一次单击时保存输入,然后在第二次单击时将其显示在 UI 中……为什么?!!!以及如何解决它
【发布时间】:2021-04-03 17:43:31
【问题描述】:

我正在制作一个带有 react 的待办事项列表应用程序,当您输入一个输入然后单击按钮创建一个新的 todoItem 对象时,我遇到了这种错误,它显示一个空对象,然后将该输入保存在 todoList 对象中生产代码中的变量,然后 第一个 todo 元素出现 在 UI 中 第二次点击,在 第三次点击 出现 第二次 todoItem、第四次点击第三个元素等等...我不知道为什么会这样,我想解决这个问题,这是我的代码:

----------APP COMPONENT-------
import React, { useState } from "react";
import Form from "./Form";
import List from "./List";

function App() {
  const [input, setInput] = useState("");
  const [todoItem, setTodoItem] = useState({});
  const [todoList, setTodoList] = useState([]);

  const addTodoItem = (e) => {
    e.preventDefault();
    input && setTodoItem({ content: input, id: Math.random() * 1000 });
    setTodoList([...todoList, todoItem]);
    setInput("");
  };

  return (
    <div>
      <Form input={input} addTodoItem={addTodoItem} setInput={setInput} />
      <List todoList={todoList} setTodoList={setTodoList} />
    </div>
  );
}

export default App;

---------FORM COMPONENT-----------
import React from "react";

function Form({ input, setInput, addTodoItem }) {
  return (
    <div>
      <form action="">
        <label>todos</label>
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="what needs to be done"
          type="text"
        />
        <button onClick={addTodoItem}>set todo</button>
      </form>
    </div>
  );
}
export default Form;


----------LIST COMPONENT-----------
import React, { useState } from "react";

function List({ setTodoList, todoList }) {
  const [completed, setCompleted] = useState(false);

  const deleteItem = (del) => {
    todoList?.map((item, i, arr) => {
      setTodoList(arr.filter((value) => value.id != del));
      console.log("item>>>", item, "index>>>>", i, "array>>>>", arr);
    });
  };
  const reverseCompleted = () =>
    completed ? setCompleted(false) : setCompleted(true);
  return (
    <div>
      <div>
        {todoList.map((item, i) => (
          <div key={i}>
            <p>{item.content}</p>
            <button onClick={() => deleteItem(item.id)}>Delete</button>
            <button onClick={reverseCompleted}>
              {completed ? "unCompleted" : "Completed"}
            </button>
          </div>
        ))}
      </div>
    </div>
  );
}

export default List;

【问题讨论】:

    标签: javascript reactjs object input rendering


    【解决方案1】:

    第一次尝试的内容是空的,因为 React 的 useState 更新了 isn't immediate。因此,您将不得不等待 todoItem 更改才能将其放入 todoList 数组中。

    一种可能的解决方案是使用 React 的 useEffect 并跟踪 todoItem 上的更改。当它发生变化并且其content 属性不为空时,您可以更新todoList

    useEffect(() => {
      if (todoItem.content) {
        setTodoList([...todoList, todoItem]);
      }
    }, [todoItem]);
    
    const addTodoItem = (e) => {
      e.preventDefault();
      input && setTodoItem({ content: input, id: Math.random() * 1000 });
      setInput("");
    };
    

    这个解决方案可能会出错,因为每当todoItem 引用发生变化时,它就会被添加到todoList,这不是您想要的。

    我建议的另一个更好的解决方案是在 addTodoItem 处理程序中声明一个新变量,并将其附加到 todoList 数组,以及调用 setTodoList

    const addTodoItem = (e) => {
      e.preventDefault();
      const newTodoItem = { content: input, id: Math.random() * 1000 };
      input && setTodoItem(newTodoItem);
      setTodoList([...todoList, newTodoItem]);
      setInput("");
    };
    

    【讨论】:

    • 但我不明白的一件事是为什么你要创建一个变量 newTodItem 为什么不直接 setTodoItem({ content: input, id: Math.random() * 1000 }) 有什么区别是不一样吗? @Kapobajza
    • @MansouriAla 我声明了变量newTodoItem,因为您可以立即在两个函数中使用它的更新值:setTodoItemsetTodoList。而如果您使用了todoItem 变量,则必须等待其值被setTodoItem useState 钩子更新,然后才能使用它。 input &amp;&amp; setTodoItem({ content: input, id: Math.random() * 1000 }); 这行执行后,todoItem 的值仍然是一个空对象,{}。所以当下一行执行时:setTodoList([...todoList, todoItem]);,它会在数组中设置一个空对象。
    • 是的,我现在明白了,我记得 useState 不会立即执行,所以下一个值将采用一个空对象,非常感谢您的解释,感谢我现在明白了
    猜你喜欢
    • 1970-01-01
    • 2013-02-27
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 2013-01-06
    • 1970-01-01
    • 2012-09-02
    • 2015-07-23
    相关资源
    最近更新 更多