如何使用 React 在 setState 上更新和显示第一个非空值?

How to update and display first non-empty value on setState with react?

我正在尝试在列表中显示我的输入值。每次我点击提交,我希望它应该按顺序显示输入。

我遇到的问题是,当我尝试提交表单并在列表中显示输入时,它首先显示一个空值。在下一次提交和此后,它会在输入字段中显示以前的值,而不是新值。

还有一条错误消息,但我不明白如何将它与问题联系起来。 It's a warning message regarding controlled/uncontrolled components.

我尝试添加 if 语句来检查每个函数中的空值,但问题 persists.I 我试图通过与所有 input 使用 setState 来控制元素,但没有任何效果。

我查看了 github 上的待办事项列表示例。我想我正试图将它保留在一个功能组件中而不是多个功能组件中,而且我没有使用 class 组件。我尝试按照 Javascript 30 天挑战第 15 天的 wesbos 教程进行操作:本地存储和事件委托。我正在尝试使用 React 而不是普通的 JS。

这是我的组件的样子。

import React, { useEffect, useState } from "react";
import "../styles/LocalStorage.css";

export const LocalStorage = () => {
  const [collection, setCollection] = useState([]);
  const [value, setValue] = useState();
  const [item, setItem] = useState({ plate: "", done: false });
  const [display, setDisplay] = useState(false);

  //set the value of the input
  const handleChange = (e) => {
    if (e.target.value === "") return;
    setValue(e.target.value);
  };

  const handleSubmit = (e) => {
    e.preventDefault();

    if (value === "" || undefined) return;
    setItem((prevState) => {
      return { ...prevState, plate: value };
    });

    addItem(item);
    setDisplay(true);
    setValue("");
  };

  const addItem = (input) => {
    if (input.plate === "") return;
    setCollection([...collection, input]);
  };

  return (
    <div>
      <div className="wrapper">
        <h2>LOCAL TAPAS</h2>

        <ul className="plates">
          {display ? (
            collection.map((item, i) => {
              return (
                <li key={i}>
                  <input
                    type="checkbox"
                    data-index={i}
                    id={`item${i}`}
                    checked={item.done}
                    onChange={() =>
                      item.done
                        ? setItem((state) => ({ ...state, done: false }))
                        : setItem((state) => ({ ...state, done: true }))
                    }
                  />
                  <label htmlFor={`item${i}`}>{item.plate}</label>
                </li>
              );
            })
          ) : (
            <li>Loading Tapas...</li>
          )}
        </ul>
        <form className="add-items" onSubmit={handleSubmit}>
          <input
            type="text"
            name="item"
            placeholder="Item Name"
            required
            value={value}
            onChange={handleChange}
          />
          <button type="submit">+ Add Item</button>
        </form>
      </div>
    </div>
  );
};

由于 setState 函数是异步的,您不能在触发 setItem(...) 后立即使用状态值 item。为确保您获得 addItem 函数的最新值:

setItem((prevState) => {
  const newItem = { ...prevState, plate: value };
  addItem(newItem); // Now, it's getting the updated value!
  return newItem;
});

关于受控和非受控组件,您可以阅读相关文档here。要解决您的问题,您可以使用空字符串初始化值状态:

const [value, setValue] = useState('');