如何在 React 中缓存组件数据,使其不会在每次加载时重新渲染?



我使用React native,在我的一个屏幕上我有一个toggle组件。该组件有2个选项,点击它们会呈现不同的数据。我注意到ios上的性能不差,但在Android上很糟糕,我希望它在两个平台上都很好(显然)

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

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

但是,当我来回切换时,我看到组件控制台。日志被触发,我也看到控制台。调用.map函数内部的日志。这是意料之中的吗?我希望React.memo只会重新渲染,如果道具改变?

是否有其他缓存策略可以解决这个问题,使其性能更高?

更多细节所以两个组件是LeaguePrevious Games,我基本上是从我的redux存储映射到LeaguePrevious Games中的数据,它需要一个games的道具并映射到它。这是一个相当昂贵的函数,事实证明,当我用Text字符串替换地图时,切换似乎发生得更快。当我说道具不会变的时候,我的意思就是。Previous Games加载新数据的应用程序加载,但它永远不会改变(直到这种情况再次发生)。也就是说,每次切换时,道具保持不变

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

反应。当props相同时,memo将跳过重新渲染,即浅等于.

如果你的组件在给定相同的道具的情况下呈现相同的结果,你可以将它封装在对React的调用中。在某些情况下,通过记忆结果来提高性能。这意味着React将跳过渲染组件,并重用最后渲染的结果。

反应。备注只检查道具更改。如果你的函数组件包装在React中。memo在它的实现中有一个useState, useReducer或useContext钩子,当状态或上下文发生变化时,它仍然会呈现。

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

默认行为(浅比较)

示例,ChildParent都是重新渲染,即使值是相同的;

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>

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

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

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>