无限循环React挂钩

时间:2019-03-06 12:39:47

标签: 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>
}

2 个答案:

答案 0 :(得分:5)

valsetVal将在每个渲染上更改,这又将导致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"));
<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>

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

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"));
<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>

答案 1 :(得分:0)

看看您想做什么,我相信您缺少Hooks&React最有用的功能之一,那就是组成。

这是您所做的事的一个示例,但是对我来说,只需创建另一个名为<IncrementButton/>的组件,就可以使代码更容易理解/调试。自定义钩子很棒,但是我相信这样做是错误的工具。

const { useEffect, useState } = React;

const IncrementButton = props => {
  const {val, setVal, children} = props;
  return <button
    onClick={() => setVal(val + 1)}
  >{children}</button>;
}

const Home = () => {
  const [val, setVal] = useState(0);
  return (
    <div>
      <div>{val}</div>
      <IncrementButton val={val} setVal={setVal}>
        Click me
      </IncrementButton>
    </div>
  );
};

ReactDOM.render(<Home />, document.getElementById("root"));
<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>

相关问题