新的反应钩困惑



我是新来的,与React Hooks功能组件相关,我有一些问题需要解释,谢谢:

  1. 我如何在重新渲染之前对某些状态进行深入比较?我看到了反应。Memo只有第二个论点仅用于修改道具的比较,但是国家呢?当前,它使用对象。I进行比较,我想修改此功能。

  2. usememo的Usecallback的原则是什么?我已经调查了React源代码,但仍然不知道该如何执行此操作。有人给我一个简单的例子来说明如何知道如何缓存每个渲染的值?

Q1:在重新渲染之前,我如何对某些状态进行深入比较?

在下面的摘要中,我向您展示了对状态进行深入比较的一种方法。

Q2:Usecallback,UseMeMo?

的原理是什么

useMemo旨在在您有一些昂贵的计算情况下要记住结果的情况。因此,昂贵的计算仅对inputs的每个唯一组合进行一次。

useCallback旨在避免重新创建不需要重新创建的内部功能。除非依赖项数组中列出的某些变量更改。通常用作性能优化。

根据React文档:

usecallback

将回调传递给优化的儿童组件时,这很有用,这些组件依靠参考均等性来防止不必要的渲染(例如,shordcomponentupdate(。

注意:

状态更改是为了引起重新渲染。为什么要在重新渲染之前对其进行深入比较?如果更改,React必须重新渲染。这就是它的工作方式。

如果您想改变某些东西而不引起重新渲染,请查看useRef钩子。这正是它的作用。ref对象在每个渲染中保持不变(仅当组件被卸载然后重新安装时更改(。

https://reactjs.org/docs/hooks-reference.html#useref

useref

USEREF返回一个可突出的Ref对象,其.Crurnent属性被初始化为传递的参数(初始值(。返回的对象将持续到组件的整个生命周期。

(...(

但是,useref((对不比ref属性更有用。对于,请保持任何可变值的方便,类似于您在类中使用实例字段的方式。

代码

比较Newstate和Laststate

function App() {
  const [myState, setMyState] = React.useState('Initial state...');
  const lastState_Ref = React.useRef(null);
  const stateChanged_Ref = React.useRef(null);
  
  
  
  if (lastState_Ref.current !== null) {
    lastState_Ref.current === myState ?   // YOU CAN PERFORM A DEEP COMPARISON IN HERE
      stateChanged_Ref.current = false
    : stateChanged_Ref.current = true;
  }
  
  lastState_Ref.current = myState;
  function handleClick() {
    setMyState('New state...');
  }
  return(
    <React.Fragment>
      <div>myState: {myState}</div>
      <div>New state is different from last render: {JSON.stringify(stateChanged_Ref.current)}</div>
      <button onClick={handleClick}>Click</button>
    </React.Fragment>
  );
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

更新:

从您的评论中,您对props的能力是使用React.memo。它将对您的道具进行比较。请参阅下面的摘要。您会看到常规Child每次都会重新渲染,如果阵列propA保持不变,则包裹在React.memo中的ChildMemo不会重新渲染。

react.memo

react.memo是一个高阶组件。它类似于react.purecomponent,但对于功能组件而不是类。

如果您的功能组件在相同的道具下呈现相同的结果,则可以将其包装在呼叫中。这意味着React会跳过渲染组件,并重复使用最后一个渲染的结果。

默认情况下,它将仅比较道具对象中的复杂对象。如果要控制比较,也可以提供自定义比较功能作为第二个参数。

这是对这种情况的React Docs建议:

https://reactjs.org/docs/hooks-faq.html#how-do-i-i-implement-shouldcomponentupdate

function App() {
  console.log('Rendering App...');
  
  const [myState,setMyState] = React.useState([1,2,3]);
  const [myBoolean,setMyBoolean] = React.useState(false);
  
  return(
    <React.Fragment>
      <button onClick={()=>setMyBoolean((prevState) => !prevState)}>Force Update</button>
      <Child
        propA={myState}
      />
      <ChildMemo
        propA={myState}
      />
    </React.Fragment>
  );
}
function Child() {
  console.log('Rendering Child...');
  
  return(
    <div>I am Child</div>
  );
}
const ChildMemo = React.memo(() => {
  console.log('Rendering ChildMemo...');
  return(
    <div>I am ChildMemo</div>
  );
});
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

关于状态,我认为您不应该尝试实现这一目标。如果国家发生变化,它应该重新渲染。实际上,如果状态引用(对象或数组(保持不变,则不会重新渲染。因此,如果您不更改state参考(例如从刮擦相同的数组或对象重新创建(,则您已经将该行为从开箱即用。您可以在下面的摘要上看到:

function App() {
  console.log('Rendering App..');
  const [myArrayState,setMyArrayState] = React.useState([1,2,3]);
  
  function forceUpdate() {
    setMyArrayState((prevState) => {
      console.log('I am trying to set the exact same state array');
      return prevState;                     // Returning the exact same array
    });
  }
  
  return(
    <React.Fragment>
      <div>My state is: {JSON.stringify(myArrayState)}</div>
      <button onClick={forceUpdate}>Reset State(see that I wont re-render)</button>
    </React.Fragment>
  );
}
ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>

添加到 cbdev420 说的是,这是一个备忘单的链接,该链接可以很好地解释如何使用大多数钩子,如果它可以帮助您https://reeact-hooks-cheatsheet.surge.sh/

相关内容

  • 没有找到相关文章

最新更新