【问题标题】:Why doesn't React update my state correctly? [duplicate]为什么 React 不能正确更新我的状态? [复制]
【发布时间】:2021-12-11 06:18:18
【问题描述】:

我通过使用 map 函数迭代它来显示我的状态,它是一个数组。此外,我有一个按钮可以在单击时反转数组。

import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
import "./App.css";

const App = (props) => {
  const [reverse, setReverse] = useState(false);

  const [arr, setArr] = useState([]);

  useEffect(() => {
    let newArr = props.arr;

    newArr = newArr.reverse();

    setArr(newArr);
  }, [reverse, props.arr]);

  return (
    <div className="App">
      <button
        onClick={() => {
          setReverse(!reverse);
        }}
      >
        Reverse
      </button>
      {arr.map((e, i) => {
        return (
          <div key={i}>
            <p>{e}</p>
          </div>
        );
      })}
    </div>
  );
};

App.propTypes = {
  arr: PropTypes.array,
};

export default App;

我认为我想做什么是相当明显的。但这对我不起作用,我不知道为什么。我必须单击两次才能完成第一次还原,然后出现奇怪的情况,其中呈现的数组与 Chrome 中的 React 开发工具在组件状态中显示的数组不匹配。

我无法解释这种行为。我开始认为这与我从道具中获取数组的事实有关,但我真的不知道。有什么想法吗?

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    主要的错误是你将你的道具分配给newArr变量,而不是arr,所以每次都不是arr的新状态 这是相反的,但props的原始数组。另外,在更改props 时,最好多加一个useEffect。我在下面提供了正确代码的示例 如果有错误我很抱歉,我的英语说得不好

      useEffect(() => {
        setArr(props.arr);
      }, [props.arr]);
    
      useEffect(() => {
        if (!arr.length) return;
    
        let newArr = arr.length ? [...arr] : [...props.arr];
        newArr = [...newArr.reverse()];
        setArr(newArr);
      }, [reverse]);
    

    【讨论】:

      【解决方案2】:

      有几处需要改进。有些是错误,有些只是反模式。

      首先要注意的是reverse 改变了原始数组。你不应该在 React 中改变 state 或 props。

      第二种是一种反模式,涉及将道具复制到不需要的状态。

      React docs 说状态是用于随时间变化的值。它表示如果一个值可以从 props 派生,则它是 not 状态。

      您可以根据组件中的任何其他状态或道具来计算它吗?如果是这样,它就不是状态。

      这就是我们在这种情况下所拥有的。

      与其将 prop arr 复制到 state 中并在那里反转它,我们可以使用 prop 和一个临时变量以更少的代码实现相同的目标。

      const {useState, useEffect} = React;
      
      const App = (props) => {
        const [reverse, setReverse] = useState(false);
        
        let array = [...props.arr]; // New reference so we will not mutate props
        if (reverse) {
          array.reverse();
        }
      
        return (
          <div className="App">
            <button
              onClick={() => {
                setReverse(!reverse);
              }}
            >
              Reverse
            </button>
            {array.map((e, i) => {
              return (
                <div key={i}>
                  <p>{e}</p>
                </div>
              );
            })}
          </div>
        );
      };
      
      ReactDOM.render(<App arr={[1,2,3]} />, document.getElementById('root'));
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
      <div id="root"></div>

      【讨论】:

        【解决方案3】:

        这是因为 useEffect() 钩子在您的组件的挂载上运行并反转您的数组,尽管您没有单击反转按钮。

        尝试添加逻辑以避免安装上发生的第一次反转。

        这可能对你有用,

          useEffect(() => {
              if(arr.length>0){
                 let newArr = props.arr;
                 newArr = newArr.reverse();
                 setArr(newArr);
              }
          }, [reverse, props.arr]);
        

        【讨论】:

          猜你喜欢
          • 2020-07-11
          • 1970-01-01
          • 2021-12-13
          • 2011-04-23
          • 2021-06-07
          • 2021-02-12
          • 2019-11-05
          • 2019-03-04
          • 1970-01-01
          相关资源
          最近更新 更多