我有一个关于React的问题shouldComponentUpdate(当没有被覆盖时).我更喜欢纯粹的功能组件,但我担心它每次都会更新,即使道具/状态没有改变.所以我正在考虑使用PureComponent类.
我的问题是:功能组件shouldComponentUpdate是否与PureComponents 具有相同的检查?或者它每次更新?
the*_*eff 16
无论道具是否更改,功能组件都会在父母每次渲染时重新渲染。
但是,使用React.memo高阶组件实际上可以使功能组件获得与https://reactjs.org/docs/react-api.html#reactmemo中shouldComponentUpdate使用的检查相同的检查PureComponent 
您可以简单地将功能组件包装React.memo在导出文件上,如下所示。
所以
const SomeComponent = (props) => (<div>HI</div>)
export default SomeComponent
可能是
const SomeComponent = (props) => (<div>HI</div>)
export default React.memo(SomeComponent)
例
以下示例显示了这如何影响转售
父组件只是常规功能组件。它正在使用新的react挂钩来处理一些状态更新。
它只是具有某种tick状态,该状态仅用于提供一些线索,说明我们重新渲染道具的频率,而它每秒强制两次渲染父组件。
此外,我们有一个clicks状态,可以告诉我们单击按钮的频率。这就是我们送给孩子们的道具。因此,如果我们使用点击次数,则仅应重新显示点击次数React.memo
现在注意,我们有两种不同的孩子。一包,memo另一包没有。Child它没有包装,将在父母每次重新渲染时重新渲染。MemoChild包装的内容,仅在clicks属性更改时才会重新呈现。
const Parent = ( props ) => {
  // Ticks is just some state we update 2 times every second to force a parent rerender
  const [ticks, setTicks] = React.useState(0);
  setTimeout(() => setTicks(ticks + 1), 500);
  // The ref allow us to pass down the updated tick without changing the prop (and forcing a rerender)
  const tickRef = React.useRef();
  tickRef.current = ticks;
  // This is the prop children are interested in
  const [clicks, setClicks] = React.useState(0);
  return (
    <div>
      <h2>Parent Rendered at tick {tickRef.current} with clicks {clicks}.</h2>
      <button 
        onClick={() => setClicks(clicks + 1)}>
        Add extra click
      </button>
      <Child tickRef={tickRef} clicks={clicks}/>
      <MemoChild tickRef={tickRef} clicks={clicks}/>
    </div>
  );
};
const Child = ({ tickRef, clicks }) => (
  <p>Child Rendered at tick {tickRef.current} with clicks {clicks}.</p>
);
const MemoChild = React.memo(Child);
您可以在这里查看示例https://codepen.io/anon/pen/ywJxzV
Yad*_*ran 13
在React中,功能组件是无状态的,并且它们没有生命周期方法.无状态组件是编写React组件的优雅方式,在我们的包中没有太多代码.但在内部,无状态组件被包装在一个类中,而当前没有任何优化.这意味着无状态和有状态组件在内部具有相同的代码路径(尽管我们以不同方式定义它们).
但是在未来,React可以优化无状态组件,如下所述:
将来,我们还可以通过避免不必要的检查和内存分配来针对这些组件进行性能优化.[更多阅读...]
shouldComponentUpdate这是我们可以应用自定义优化并避免不必要的重新呈现组件的地方.下面介绍了使用不同类型组件的此方法:
功能无状态组件
如前所述,无状态组件没有生命周期方法,因此我们无法使用它们进行优化shouldComponentUpdate.但它们已经以不同的方式进行了优化,它们具有更简单和优雅的代码结构,并且比具有所有生命周期钩子的组件花费更少的字节.
扩展React.PureComponent
从React v15.3.0开始,我们有一个新的基类PureComponent 
,使用PureRenderMixin内置函数进行扩展.在引擎盖下,这采用了当前道具/状态与a中的下一个道具/状态的浅层比较shouldComponentUpdate.
也就是说,我们仍然不能依靠PureComponent类来将我们的组件优化到我们想要的水平.如果我们有Object类型(数组,日期,普通对象)的道具,就会发生这种异常情况.这是因为我们在比较对象时遇到这个问题:
const obj1 = { id: 1 };
const obj2 = { id: 1 };
console.log(obj1 === obj2); // prints false
因此,浅层比较不足以确定事情是否发生了变化.但PureComponent如果你的道具只是字符串,数字,布尔值而不是对象,请使用类.如果您不想实现自己的自定义优化,也可以使用它.
扩展React.Component
考虑上面的例子; 如果我们知道如果id已经改变了对象已经改变了,那么我们可以通过比较来实现我们自己的自定义优化obj1.id === obj2.id.这就是extend我们普通Component基类的用武之地,也可以shouldComponentUpdate用来比较特定的键.
kru*_*kat 13
这里已经有很多很好的答案。我只是想添加一个示例,您想要专门比较一个道具(而不是所有道具)并决定基于此重新渲染。
下面是一个我只想在字符串属性更改Header时重新渲染的组件。heading
import React from 'react'
const Header = ({ heading }) => {
  console.log('Header')
  return (
    <h2 className='bg-gray-300 text-gray-800 text-center py-6 px-8 rounded-md text-xl font-extrabold'>
      {heading}
    </h2>
  )
}
const areEqual = (prevProps, nextProps) => {
  if (prevProps.heading === nextProps.heading) {
    return true                                    // donot re-render
  }
  return false                                     // will re-render
}
export default React.memo(Header, areEqual)
关于返回值的关键areEqual是:
return true=> 不重新渲染return false=> 将重新渲染我从这里的官方文档中得到了这个
另一种方法是使用useMemo仅在更新监视值时更新值:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
在对象的情况下,在确保更新后,可以选择使用状态挂钩来缓存感兴趣变量的值。例如通过使用lodash:
const [fooCached, setFooCached]: any = useState(null);
if (!_.isEqual(fooCached, foo)) {
  setFooCached(foo);
}). 
const showFoo = useMemo(() => {
    return <div>Foo name: { foo.name }</div>
}, [fooCached]);
| 归档时间: | 
 | 
| 查看次数: | 9956 次 | 
| 最近记录: |