无限循环React挂钩

Оре*_*кий 4 javascript reactjs react-hooks

我不明白为什么useClick中会出现无限循环, 我看到我使用setVal更改了useEffect中的状态值,但useEffect应该仅在第二个参数中指定的onClick上起作用。我认为这是因为我传递的参数onClick被记录下来,但未调用回调(我使用console.log('go set'检查过)

function useClick(onClick, setVal, val) {
  React.useEffect(() => {
    console.log('Click');
    setVal(val + 1);
  }, [onClick]);
}

const Home = () => {
  const [val, setVal] = React.useState(0);
  const incrementOnClick = React.useCallback(() => {
    console.log('go set');
    setVal(val + 1);
  } , [setVal, val]);
  useClick(incrementOnClick, setVal, val);
  return <div>
    <div>{val}</div>
    <button onClick={incrementOnClick}>Click me</button>
 </div>
}
Run Code Online (Sandbox Code Playgroud)

Tho*_*lle 7

val并且setVal会在每次渲染时更改,从而导致incrementOnClick成为新的函数引用,并且useClick始终会调用您的效果。

您可以改为将函数作为第一个参数setVal。此函数获取当前值val作为参数并返回新值。这种方式incrementOnClick将始终是相同的功能。

const { useEffect, useState, useCallback } = React;

function useClick(onClick, setVal, val) {
  useEffect(() => {
    console.log("Click");
    setVal(val + 1);
  }, [onClick]);
}

const Home = () => {
  const [val, setVal] = useState(0);
  const incrementOnClick = useCallback(() => {
    console.log("go set");
    setVal(val => val + 1);
  }, []);

  useClick(incrementOnClick, setVal, val);

  return (
    <div>
      <div>{val}</div>
      <button onClick={incrementOnClick}>Click me</button>
    </div>
  );
};

ReactDOM.render(<Home />, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)

上面的代码显示了如何摆脱无限循环并可能对实验有价值,但是其中大部分不是必需的。您可以这样编写相同的功能:

const { useState } = React;

const Home = () => {
  const [val, setVal] = useState(1);
  
  return (
    <div>
      <div>{val}</div>
      <button onClick={() => setVal(val + 1)}>Click me</button>
    </div>
  );
};

ReactDOM.render(<Home />, document.getElementById("root"));
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>
Run Code Online (Sandbox Code Playgroud)