[英]Fail to prevent re-render by React.memo
I am building a react native app for which has a form page contains a lot of textInput and buttons.我正在构建一个反应本机应用程序,其表单页面包含大量文本输入和按钮。 Each of fields do not causing performance issue.
每个字段都不会导致性能问题。
However, when they are put together, the application will show js thread frame drops in the Perf Monitor.但是,当它们放在一起时,应用程序将在 Perf Monitor 中显示 js 线程帧丢失。 So I think the page is re-rendering all the components when any of the state is changed.
因此,我认为当 state 中的任何一个发生更改时,页面都会重新呈现所有组件。
I tried 2 methods.我尝试了2种方法。
React.memo
.React.memo
。 Unfortunately, both of them are not working.不幸的是,它们都不起作用。 The app still lag and re-render every time for all components.
该应用程序仍然滞后并每次为所有组件重新呈现。
So I created a simple case for it.所以我为它创建了一个简单的案例。 You may see the code below.
您可能会看到下面的代码。
I would like to only re-render the ChildItem
for only the respective state changed.我只想为相应的 state 更改重新呈现
ChildItem
。 For now, console will log from 1 to 5 for any button clicked.现在,控制台将为单击的任何按钮记录 1 到 5。 Since the
props
passed to memo component is not changed, I expect the console will only log 1 respective sentence for specific index when button is pressed.由于传递给备忘录组件的
props
没有改变,我希望当按下按钮时,控制台只会为特定索引记录 1 个相应的句子。
import React, {useState, memo} from 'react';
import { View, Text, Button } from 'react-native';
const ChildeItem = memo( ({index, value, onPress}) =>{
console.log(`ChildeItem ${index} rendered`);
return(
<View style={{flexDirection: 'row'}}>
<Text style={{flex: 1, textAlign: 'center'}}>
{value}
</Text>
<View style={{flex: 1}}>
<Button
onPress={onPress}
title={"+"}
/>
</View>
</View>
)
});
export default function TestScreen({navigation}) {
const [value1, setValue1] = useState(0);
const [value2, setValue2] = useState(0);
const [value3, setValue3] = useState(0);
const [value4, setValue4] = useState(0);
const [value5, setValue5] = useState(0);
return(
<View>
<ChildeItem index={1} value={value1} onPress={()=>{setValue1(value1+1);}} />
<ChildeItem index={2} value={value2} onPress={()=>{setValue2(value2+1);}} />
<ChildeItem index={3} value={value3} onPress={()=>{setValue3(value3+1);}} />
<ChildeItem index={4} value={value4} onPress={()=>{setValue4(value4+1);}} />
<ChildeItem index={5} value={value5} onPress={()=>{setValue5(value5+1);}} />
</View>
)
}
Or I have any misunderstanding for React.memo
?或者我对
React.memo
有什么误解? Any help will be appreciated.任何帮助将不胜感激。 Thanks.
谢谢。
Your index
and value
props are ok for memoization, but your onPress
prop causes re-render because on every render of the TestScreen, your onPress prop functions are re-created, so it's reference changes.您的
index
和value
道具可以用于记忆,但是您的onPress
道具会导致重新渲染,因为在 TestScreen 的每次渲染中,都会重新创建您的 onPress 道具功能,因此它是参考更改。 You can prevent this by usinguseCallback
hook.您可以使用
useCallback
挂钩来防止这种情况。
export default function TestScreen({navigation}) {
const [value1, setValue1] = useState(0);
const [value2, setValue2] = useState(0);
const [value3, setValue3] = useState(0);
const [value4, setValue4] = useState(0);
const [value5, setValue5] = useState(0);
// Use useCallback for each function
const onPress1 = useCallback(() => setValue1(value1+1), [value1]);
const onPress2 = useCallback(() => setValue2(value2+1), [value2]);
const onPress3 = useCallback(() => setValue3(value3+1), [value3]);
const onPress4 = useCallback(() => setValue4(value4+1), [value4]);
const onPress5 = useCallback(() => setValue5(value5+1), [value5]);
return(
<View>
<ChildeItem index={1} value={value1} onPress={onPress1} />
<ChildeItem index={2} value={value2} onPress={onPress2} />
<ChildeItem index={3} value={value3} onPress={onPress3} />
<ChildeItem index={4} value={value4} onPress={onPress4} />
<ChildeItem index={5} value={value5} onPress={onPress5} />
</View>
)
}
By using useCallback
hook, you're memoizing the onPress functions, so they are re-created only when the relevant value changes.通过使用
useCallback
挂钩,您正在记住 onPress 函数,因此只有当相关值发生变化时才会重新创建它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.