【问题标题】:UseState not saving user input [duplicate]UseState不保存用户输入[重复]
【发布时间】:2021-01-21 18:21:29
【问题描述】:

我正在使用 useState 处理待办事项应用程序,我试图保存用户输入,然后在他们单击提交后将其推送到 listArray,稍后显示它... 我认为我在 updateArray 函数中做错了,但我似乎明白了什么。

import React, { useState } from "react";

function App() {
  const listArray = [""];

  const [list, updateList] = useState("");

  function handleChange(event) {
    const { name, value } = event.target;

    updateList(value);
    //console.log(list);
  }
  
  function updateArray() {
    console.log(list);

    listArray.push(list);
    console.log(listArray);
  }

  return (
    <div className="container">
      <div className="heading">
        <h1>To-Do List</h1>
      </div>
      <div className="form">
        <input name="entry" onChange={handleChange} type="text" />
        <button>
          <span onSubmit={updateArray}>Add</span>
        </button>
      </div>
      <div>
        <ul>
          <li>{listArray[0]}</li>
        </ul>
      </div>
    </div>
  );
}

export default App;

【问题讨论】:

    标签: javascript reactjs react-hooks use-state


    【解决方案1】:

    您当前的代码存在几个问题,我将简要描述并提供解决方案。

    1. 您的函数工作正常且符合预期,但在 React 应用程序中,重新渲染页面或组件的方法很少,更改局部变量不是其中之一。所以你需要使用本地状态而不是本地 listArray 变量。由于已经存在一种状态,您应该定义另一种状态,或者将当前状态设为对象并将与组件相关的状态放入其中,我将采用第二种方法,因为它更优雅、更简洁。
    const [state, setState] = useState({ list: [], input: "" });
    
    1. 定义状态后,您需要正确更改它们而不影响不必要的状态。您只需要发送之前的状态,将其保存在新的状态中,并且只需更改每个函数中的相关状态即可。因此,使用 ES6 语法,更新 input 状态将如下所示:
    setState((prev) => ({ ...prev, input: value })); // immediate return "({})" of an object with iterating through the previous values "...prev" and updating input "input: value"
    

    注意:您可以阅读有关扩展运算符 (...) here 的更多信息。

    所以您的 handleupdateArray 函数将如下所示:

    function handleChange(event) {
      const { value } = event.target;
      setState((prev) => ({ ...prev, input: value }));
    }
    
    function updateArray() {
      setState((prev) => ({ ...prev, list: [...state.list, state.input] }));
    }
    
    1. onSubmit 事件仅适用于表单或提交按钮,因此您需要将其更改为 onClick。此外,要使整个按钮捕捉到 onclick 操作,您需要在按钮本身而不是 span 元素上设置它。
    <button onClick={updateArray}> <!-- It's better to assign onclick action to an element with a function or arrow function to prevent it from running in the first render "(event) => updateArray(event)" -->
      <span>Add</span> 
    </button>
    
    1. 最后,您需要映射 JSX 中更新后的待办事项数组。
    <ul>
      {state.list.map((item, index) => (
          <li key={index}>{item}</li>
      ))}
    </ul>
    

    工作演示:

    【讨论】:

      【解决方案2】:

      将当前值保存到状态中,并将列表也保存到状态中,这样它就不会在每个渲染周期中被清除。

      import React, { useState } from "react";
      
      function App() {
        const [list, updateList] = useState([]);
        const [currentValue, setCurrentValue] = useState()
      
        function handleChange(event) {
          setCurrentValue(event.target.value)
        }
      
        function handleClick() {
          updateList([...list, currentValue])
        }
      
        return (
          <div className="container">
            <div className="heading">
              <h1>To-Do List</h1>
            </div>
            <div className="form">
              <input name="entry" onChange={handleChange} type="text" />
              <button type="button" onClick={handleClick}>
                <span>Add</span>
              </button>
            </div>
            <div>
              <ul>
                {list.map((res) => (
                  <li key={res}>{res}</li>
                ))}
              </ul>
            </div>
          </div>
        );
      }
      
      export default App;
      

      此外,将 onClick 移至按钮在语义上(甚至对于 UX)更有意义,但这取决于您。

      【讨论】:

      • 我已经更新了您的答案,因此它专注于您所做的实际更改,这些更改大多是有效的。我恢复了事件处理程序道具,因为没有必要将它们包装在额外的箭头函数中。请随时根据自己的情况调整文本并查看我所做的更改。
      【解决方案3】:

      请注意,当您的应用组件重新渲染时,listArray 将始终返回默认值(使用 useState 可能会重新渲染组件)

      我会改为将用户输入的字符串设为普通 const 并使用 useState 作为数组,这样数组中的值将在重新渲染时保存

      【讨论】:

        【解决方案4】:

        listArray 在每次重新渲染时都会被清除。 您应该将数据存储在状态中。所以

        const [listArray, setListArray] = useState([])

        updateArray 应该是这样的:

        function updateArray() {
            setListArray([...listArray, list]);
        }
        

        我猜,updateArray 函数中应该有一些逻辑来清除list

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-02-12
          • 2010-11-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多