使用多个 setHook 会使组件渲染不止一次?

IT技术 reactjs react-hooks
2021-05-13 23:09:28

如果我有很多useState并且点击一个按钮我调用 multiple setHook,它会呈现多次还是只呈现一次?

例如

export default function setMultipleHooks() {

    const [hook1, setHook1] = useState(false)
    const [hook2, setHook2] = useState(false)
    const [hook3, setHook3] = useState(false)
    const [hook4, setHook4] = useState(false)

    const setHooks = () => {
        setHook1(true)
        setHook2(true)
        setHook3(true)
        setHook4(true)
    }

    return (
        <button onClick={setHooks} >Hey</button>
    )

}

单击按钮后,它会渲染多少次?1次还是4次?

通常为了检查组件渲染了多少次,我只是console.logrender方法中放了一个,但是对于功能组件,我不确定如何测试它。

如果渲染 4 次,useState如果 4 个钩子总是相关的,最好只使用一个(传递一个对象)?

2个回答

React 可以批处理多个 setState 调用并一次渲染它们。在您的情况下,它会这样做,因为您在事件处理程序 (onClick) 中。

正如您从下面的代码段中看到的那样,它只渲染一次(不包括初始渲染)。

关于 React 批处理 setState() 调用的 Github 问题

不过,您可以使用具有 4 个属性的对象而不是 4 个状态挂钩变量。但是在更新状态时您必须小心,因为钩子的 setState() 不会自动将您的上一个状态与您的新状态属性合并。它用您传递的新对象完全替换状态。

React Docs - 使用状态钩子

所以你必须做这样的事情:

function YourComponent() {
  const INITIAL_STATE = {a: false, b: false, c: false, d: false};
  const [state,setState] = useState(INITIAL_STATE);

  function handleClick() {
    setState((prevState) => {
      return({
        ...prevState,
        b: true
      });
    });
  }

}

const { useState, useRef, useEffect } = React;

function App() {

  const renderTimes = useRef(0);

  const [hook1, setHook1] = useState(false);
  const [hook2, setHook2] = useState(false);
  const [hook3, setHook3] = useState(false);
  const [hook4, setHook4] = useState(false);
  
  const setHooks = () => {
    setHook1(true);
    setHook2(true);
    setHook3(true);
    setHook4(true);
  }

  useEffect( () => {
    renderTimes.current+=1;
  });

  return (
    <div>
      <div>I rendered {renderTimes.current} time(s).</div>
      <div>NOTE: The initial render is not included.</div>
      <div>State hook1 is equal to: {hook1.toString()}</div>
      <div>State hook2 is equal to: {hook2.toString()}</div>
      <div>State hook3 is equal to: {hook3.toString()}</div>
      <div>State hook4 is equal to: {hook4.toString()}</div>
      <button onClick={setHooks}>Click</button>
    </div>
  );
}

ReactDOM.render(<App />, 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>

通常为了检查组件渲染了多少次,我只是在渲染方法中放置了一个 console.log,但是对于功能组件,我不确定如何测试它。

只需将 console.log 放在函数中(函数本身就是render方法)。它只会渲染一次,因为有一个很小的时间间隔,如果多次调用 useState setter,它们的更新将被批处理。

如果渲染 4 次,如果 4 个钩子总是相关的,最好只使用一个 useState(传递一个对象)?

如果你有复杂的状态,你真的应该考虑useReducer.


更多的:

https://stackoverflow.com/a/54716601/10995369

https://github.com/acdlite/react-fiber-architecture