多次调用同一setter致重渲染过多的React Native性能问题
解决React Native点击单词触发全组件重渲染的性能问题
问题分析
你遇到的核心问题是:每次点击单词调用setWordModalVisible更新状态时,Main组件会重渲染,导致所有MyText组件跟着重渲染。用React.memo没生效的原因有两点:
- 每次
Main重渲染时,handleTextPress函数会被重新创建,传递给MyText的onPressprops引用每次都变,React.memo的浅比较会判定props更新,触发重渲染。 MyText组件定义在Main内部,每次Main重渲染都会重新定义这个组件,React会认为是全新的组件类型,直接卸载重建,完全绕过React.memo的优化。
解决方案
步骤1:用useCallback缓存点击事件函数
useCallback可以在组件重渲染时保持函数引用不变,避免因函数引用变化导致子组件重渲染。
步骤2:将MyText组件移到Main外部
把组件定义移到父组件外部,避免每次父组件重渲染时重新创建组件类型。
步骤3:用React.memo包裹MyText组件
确保当props没有变化时,组件不会触发重渲染。
修改后的代码
import React, { useState, useCallback } from 'react'; import { Text, StyleSheet } from 'react-native'; // 把MyText移到Main外部,并使用React.memo包裹 interface TextProps { onPress: () => void; children: React.ReactNode; } const MyText = React.memo<TextProps>(({ onPress, children }) => { return <Text onPress={onPress}>{children}</Text>; }); export default function Main() { const [wordModalVisible, setWordModalVisible] = useState(false); // 用useCallback缓存handleTextPress,依赖为空则仅初始化时创建一次 const handleTextPress = useCallback(() => { setWordModalVisible(true); }, []); return ( <Text adjustsFontSizeToFit={true} style={styles.contentText}> <MyText onPress={handleTextPress}>Text 1</MyText> <MyText onPress={handleTextPress}>Text 2</MyText> <MyText onPress={handleTextPress}>Text 3</MyText> <MyText onPress={handleTextPress}>Text 4</MyText> <MyText onPress={handleTextPress}>Text 5</MyText> </Text> ); } const styles = StyleSheet.create({ contentText: { // 自定义样式 } });
额外优化建议
如果后续需要给每个单词传递专属参数(比如把点击的单词内容传入模态框),可以让handleTextPress接收参数,同时保持函数引用稳定:
const handleTextPress = useCallback((word: string) => { setCurrentWord(word); // 先缓存点击的单词 setWordModalVisible(true); }, []);
然后在MyText调用时传递参数:
<MyText onPress={() => handleTextPress("Text 1")}>Text 1</MyText>
如果担心箭头函数导致props变化,也可以把单词作为额外props传给MyText,让组件内部处理点击逻辑,进一步减少不必要的重渲染。
内容的提问来源于stack exchange,提问作者Anar Mamedov
相关产品推荐
相关产品推荐

