我使用React native,在我的一个屏幕上我有一个toggle组件。该组件有2个选项,点击它们会呈现不同的数据。我注意到ios上的性能不差,但在Android上很糟糕,我希望它在两个平台上都很好(显然)
每次切换时道具和状态都不会改变,所以它应该能够快速渲染?第二个屏幕是我看到更大的问题。但本质上是一个相当大的数组,呈现一个列表,每个列表中都有列表。
我试过使用这个:export const CachedPreviousGames = React.memo(PreviousGames)
,其中PreviousGames
是有问题的组件
但是,当我来回切换时,我看到组件控制台。日志被触发,我也看到控制台。调用.map
函数内部的日志。这是意料之中的吗?我希望React.memo
只会重新渲染,如果道具改变?
是否有其他缓存策略可以解决这个问题,使其性能更高?
更多细节所以两个组件是League
和Previous Games
,我基本上是从我的redux存储映射到League
和Previous Games
中的数据,它需要一个games
的道具并映射到它。这是一个相当昂贵的函数,事实证明,当我用Text
字符串替换地图时,切换似乎发生得更快。当我说道具不会变的时候,我的意思就是。Previous Games
加载新数据的应用程序加载,但它永远不会改变(直到这种情况再次发生)。也就是说,每次切换时,道具保持不变
如果你需要更多的控制何时使用React.memo
跳过渲染,你应该编写一个自定义比较函数。您可以编写自己的自定义函数来进行比较,或者从lodash的isEqual
等库中使用。
反应。当props
相同时,memo将跳过重新渲染,即浅等于.
如果你的组件在给定相同的道具的情况下呈现相同的结果,你可以将它封装在对React的调用中。在某些情况下,通过记忆结果来提高性能。这意味着React将跳过渲染组件,并重用最后渲染的结果。
反应。备注只检查道具更改。如果你的函数组件包装在React中。memo在它的实现中有一个useState, useReducer或useContext钩子,当状态或上下文发生变化时,它仍然会呈现。
默认情况下,它只会浅层比较props对象中的复杂对象。如果希望控制比较,还可以提供自定义比较函数作为第二个参数。
默认行为(浅比较)
示例,Child
和Parent
都是重新渲染,即使值是相同的;
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>