使用钩子设置具有相同值的状态会导致重新渲染吗?

IT技术 reactjs react-hooks
2021-05-25 16:05:39

使用钩子,如果我setState使用与 相同的值调用state,它会重新渲染组件吗?

如果是,我怎样才能避免这种情况?

例如

const [state, setState] = useState(foo)

...
// any where in the code
setState(foo)

考虑到foo可以是任何事物,比如{}trueprops.bar或从所述部件(常数)的出侧可变。

3个回答

如果您setState使用相同的值调用它不会重新渲染组件

试试这个:

import React, { useState, useEffect } from "react";

const foo = { foo: 'bar' };

export default ({ name }) => {
  const [state, setState] = useState(foo);
  console.log("rendered!");
  useEffect(() => {
    setState(foo);
    console.log("state reset!");
  });

  const handleClick = () => {
    console.log("handleClick!");
    setState(foo);
    // setState({ ...foo, bar : 'baz' });
  }

  return (<div>
  <h1>Hello {name}!</h1>
  <button onClick={handleClick}>Click Me</button>
  </div>);
};

您会注意到,即使单击该按钮,该值也没有改变。它不是重新渲染组件。如果您更改您调用的参数,setState它将重新渲染组件。


这是您参考代码示例

尝试在方法中注释第一个setState并取消注释第二个handleClick以查看差异。

这是一个与 js 语法相关的问题,就像===操作一样

let times = 0
const init = {name: 'Bob'}
function App() {
  const [state, setState] = useState(init)
  function modify() {
    setState({name: 'Bob'})
  }
  function modify2() {
    setState(init)
  }
  times ++
  return (
    <div className="App">
      <p>{ times }</p>
      <button onClick={modify}>Same Value Will Rerender</button>
      <button onClick={modify2}>Same Reference Never Rerender</button>
    </div>
  );
}

这是一个代码沙盒

您可以重写包装方法:

let times = 0
const init = {name: 'Bob'}
function App() {
  const [state, setState] = useState(init)
  function modify3() {
    setState2({ name: 'Bob' })
  }
  function setState2(value) {
    if (value.name === state.name) {
      return
    }
    setState(value)
  }
  times ++
  return (
    <div className="App">
      <p>{ times }</p>
      <button onClick={modify3}>Same Value Will Not Rerender Yet</button>
    </div>
  );
}

总结一下

如果您的状态是原始值(数字、字符串、布尔值、...),则使用 setState 钩子设置相同的值不会触发 rerender如果您的状态是一个对象或数组,那么它的行为会有所不同。

https://overreacted.io/how-are-function-components-different-from-classes/
https://dmittripavlutin.com/value-vs-reference-javascript/