函数无法使用 useEffect 访问即时状态更改

时间:2021-06-08 16:40:01

标签: javascript reactjs react-hooks

我正在学习如何使用 Hooks

我正在渲染一个数组列表,删除第一个元素 onclick 状态正在该 handleclick 函数中更新,但未渲染

export default function App() {
  const [name, setName] = useState("");
  const [arry, setArry] = useState([1, 2, 3, 4, 5]);

  const _log = () => {
    let ar = arry;
    ar.shift();
    setArry(ar);
    console.log(arry, "log");
  };

  const renderlist = () => {
    console.log(arry, "--");
    if (arry.length > 1) {
      return arry.map((a) => <li>{a}</li>);
    }
  }; //

  return (
    <div className="App">
      <button onClick={_log}>shift</button>
      {renderlist()}
    </div>
  );
} ```

3 个答案:

答案 0 :(得分:0)

您需要将不同的值(数组)传递给 setArry。因为 useState 被优化为在 newValue === currValue 时不改变值。

你传递相同的数组是因为你改变了它,这是 React 中的反模式(如你所见)。

  const _log = () => {
    const [_, ...ar] = arry;
    setArry(ar);
    // or setArry(([_, ...ar]) => ar);
    console.log(arry, "log");
  };

答案 1 :(得分:0)

React 通过引用而不是值来比较对象和数组。这意味着 React 正在检查的是分配数组的内存位置,而不是数组的实际内容。只要引用保持不变,React 就不会检测到数组内部所做的任何更改。

let ar = arry;
ar.shift();
setArry(ar);

此处的 ar 变量只不过是指向当前 arry 变量的指针。当您执行 setArry(ar) 时,您所做的是再次将相同的指针分配给您的 arry 值。这就是它不渲染的原因:由于对数组的引用仍然相同,React 不知道您所做的更改

为了解决这个问题,您需要创建一个包含更改的新数组实例并将其传递给 setArry

setArry([...ar]);

这里我们使用解构来创建当前 ar 数组的副本。由于此副本是一个完全不同的元素,因此它具有不同的引用。因此,使用此新项目调用 setArry 将导致您的组件使用新值重新呈现。

答案 2 :(得分:0)

您需要在进行更改之前获取数组的副本,否则您仍将引用原始数组。

let ar = [...arry];

稍微改变你的条件:

if (arry.length > 0) {

// Get a hook function
const {useState} = React;

function Example() {

  const [name, setName] = useState("");
  const [arry, setArry] = useState([1, 2, 3, 4, 5]);

  const _log = () => {
    let ar = [...arry];
    ar.shift();
    setArry(ar);
    // console.log(arry, "log");
  };

  const renderlist = () => {
    // console.log(arry, "--");
    if (arry.length > 0) {
      return arry.map((a) => <li>{a}</li>);
    }
  }; //

  return (
    <div className="App">
      <button onClick={_log}>shift</button>
      {renderlist()}
    </div>
  );

};

// Render it
ReactDOM.render(
  <Example title="Example using Hooks:" />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>