如何在 React 中缓存组件数据,使其不会在每次加载时重新渲染? [英] How can I cache component data in React so it doesn't re-render on every load?

查看:53
本文介绍了如何在 React 中缓存组件数据,使其不会在每次加载时重新渲染?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 React Native,并且在我的一个屏幕上有一个切换组件.该组件有 2 个选项,单击它们会呈现不同的数据.我注意到在 ios 上的性能还不错,但在 Android 上却很糟糕,我希望它在两者上都很好(显然)

每次切换时道具和状态都不会改变,所以它应该能够超快地渲染它?第二个屏幕是我看到更多问题的地方.但本质上是一个相当大的数组,呈现一个包含列表的列表.

我试过使用这个:export const CachedPreviousGames = React.memo(PreviousGames) 其中 PreviousGames 是有问题的组件

然而,当我来回切换时,我看到组件 console.logs 被触发,我还看到 .map 函数中的 console.logs 被调用.这是预期的吗?我希望 React.memo 只会在道具改变时重新渲染?

是否有其他缓存策略可以解决此问题以提高性能?

更多细节

所以这两个组件是 LeaguePrevious Games,其中我基本上映射了来自 LeagueLeague 中的 redux 存储中的数据code>Previous Games 它需要一个 games 的道具并映射到它上面.这是一个相当昂贵的功能,事实证明,当我只用一个 Text 字符串替换地图时,切换似乎发生得更快.当我说道具不会改变时,我的意思是,正是如此.Previous Games 在应用加载时加载新数据,但它永远不会改变(直到再次发生这种情况).即每次我切换时,道具保持不变

解决方案

如果您需要使用 React.memo 更好地控制何时跳过渲染,您应该编写一个自定义比较函数. 您可以编写自己的自定义函数来进行比较或使用来自 lodash 的 isEqual 等库.

React.memo 将在 props 时跳过重新渲染 相同,即浅等.

<块引用>

如果您的组件在给定相同的 props 的情况下呈现相同的结果,您可以将其包装在对 React.memo 的调用中,以便在某些情况下通过记忆结果来提高性能.这意味着 React 将跳过渲染组件,并重用上次渲染的结果.

<块引用>

React.memo 只检查 prop 的变化.如果你封装在 React.memo 中的函数组件在它的实现中有 useState、useReducer 或 useContext Hook,当 state 或 context 发生变化时,它仍然会重新渲染.

<块引用>

默认情况下,它只会比较 props 对象中的复杂对象.如果您想控制比较,您还可以提供自定义比较函数作为第二个参数.

默认行为(浅比较)

例如,即使值相同",ChildParent 都会重新渲染:

const ChildMemo = React.memo(Child)函数父(){console.log('父渲染...')const [value, setValue] = React.useState([1])return }function Child({ value, setValue }) {console.log('子渲染...')return 

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></脚本><script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script><script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script><身体><div id="myDemoDiv"></div>

自定义行为(自定义/深度比较):


例如,当值相同"时,Child 不会呈现:

const ChildMemo = React.memo(Child, (prevProps, props) => {返回 _.isEqual(prevProps.value, props.value)})函数父(){console.log('父渲染...')const [value, setValue] = React.useState([1])返回 (<ChildMemo value={value} setValue={setValue}/>)}function Child({ value, setValue }) {console.log('子渲染...')返回 (<button onClick={() =>setValue([1])}>{JSON.stringify(value)}</button>)}ReactDOM.render(, document.getElementById('myDemoDiv'))

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script><script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script><script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script><身体><div id="myDemoDiv"></div>

I am using React native and on one of my screens I have a toggle component. The component has 2 options and clicking on them renders different data. I've noticed performance is not bad on ios but awful on Android and I want it to be good on both (obviously)

The props and state are not changing every time I toggle so it should just be able to render it super fast? the second screen is where I'm seeing more of an issue. but is essentially a fairly big array, rendering a list with lists inside each one.

I've tried using this: export const CachedPreviousGames = React.memo(PreviousGames) where PreviousGames is the component in question

However, when I toggle back and forth I see that the component console.logs are fired, I also see the console.logs inside the .map functions are called. is this expected? I was hoping React.memo would only re-render if the props changed?

Is there any other caching strategy I can do to fix this to make it more performant?

MORE DETAILS

so the two components are League and Previous Games where I'm basically mapping over data from my redux store in League and in Previous Games it takes a prop of games and maps over that. it's quite an expensive function, verified by the fact that when I replace the map with just a Text string, the toggle appears to happen much faster. When I say props don't change I mean, exactly that. Previous Games loads up with fresh data on app load but it never changes (until this happens again). i.e. every time I toggle, the props remain constant

解决方案

If you need more control on when to skip render using React.memo, you should write a custom compare function. You can write your own custom function to do comparison or use from some library like isEqual from lodash.

React.memo will skip re-render when props are same i.e. shallow equal.

If your component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.

React.memo only checks for prop changes. If your function component wrapped in React.memo has a useState, useReducer or useContext Hook in its implementation, it will still rerender when state or context change.

By default it will only shallowly compare complex objects in the props object. If you want control over the comparison, you can also provide a custom comparison function as the second argument.

Default behavior (shallow compare)

Example, Child and Parent both are re-rendering even when values are "same":

const ChildMemo = React.memo(Child)

function Parent() {
  console.log('parent rendering ...')
  const [value, setValue] = React.useState([1])
  return <ChildMemo value={value} setValue={setValue} />
}

function Child({ value, setValue }) {
  console.log('child rendering ...')
  return <button onClick={() => setValue([1])}>{JSON.stringify(value)}</button>
}

ReactDOM.render(<Parent />, document.getElementById('myDemoDiv'))

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<body>
<div id="myDemoDiv"></div>
</body>

Custom behavior (custom/deep compare):


Example, Child is not rendering when values are "same":

const ChildMemo = React.memo(Child, (prevProps, props) => {
  return _.isEqual(prevProps.value, props.value)
})

function Parent() {
  console.log('parent rendering ...')
  const [value, setValue] = React.useState([1])
  return (
    <ChildMemo value={value} setValue={setValue} />
  )
}

function Child({ value, setValue }) {
  console.log('child rendering ...')
  return (
    <button onClick={() => setValue([1])}>{JSON.stringify(value)}</button>
  )
}

ReactDOM.render(<Parent />, document.getElementById('myDemoDiv'))

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<body>
<div id="myDemoDiv"></div>
</body>

这篇关于如何在 React 中缓存组件数据,使其不会在每次加载时重新渲染?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆