You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已用useCallback和memo仍无法阻止FlatList重复渲染

待办事项APP FlatList重渲染问题排查

我正在开发一门编程课程的待办事项列表APP,技术栈为Firebase Realtime Database、React Native和Expo。目前待办列表渲染及点击复选框标记任务优先级的功能正常,但每次点击单个任务的优先级复选框时,整个FlatList都会重新渲染。

每个任务对象结构如下:

{id: ***, text: ***, priority: ***}

Task组件

该组件包含待办文本和标记优先级的复选框,已用React.memo包裹,仅从父组件传入单个task作为props,但仍会触发全局重渲染。代码片段如下(省略标准导入):

import { CheckBox } from '@rneui/themed';

const Task = ({ item }) => {
    console.log(item)
    
    const { user } = useContext(AuthContext);

    const onPressPriority = async () => {
            await update(ref(database, `users/${user}/tasks/${item.id}`), {
                priority: !item.priority,
            });
        };

    return (
        <View
            style={{ flexDirection: 'row', alignItems: 'center', width: '95%' }}
        >
            <View
                style={{ width: '90%' }}
            >
                <Text>{item.text}</Text>
            </View>
            <View
                style={{ width: '10%' }}
            >
                <CheckBox
                    checked={item.priority}
                    checkedColor="#00a152"
                    iconType="material-community"
                    checkedIcon="checkbox-marked"
                    uncheckedIcon={'checkbox-blank-outline'}
                    onPress={onPressPriority}
                />
            </View>
        </View>
        )
}

export default memo(Task, (prevProps, nextProps) => { 
    if (prevProps.item !== nextProps.item) {
        return true
    }
    return false
})

待办列表父组件

该组件包含渲染Task组件列表的FlatList,通过useEffect监听Firebase数据库变化更新tasks状态。曾尝试将更新优先级的函数用useCallback包裹后传入子组件,但点击复选框时所有列表项仍会重渲染。代码片段如下(省略标准导入):

export default function Home2() {
  const { user } = useContext(AuthContext);
  const [tasks, setTasks] = useState([]);

  useEffect(() => {
    if (user) {
      return onValue(ref(database, `users/${user}/tasks`), (snapshot) => {
        const todos = snapshot.val();
        const tasksCopy = [];
        for (let id in todos) {
          tasksCopy.push({ ...todos[id], id: id });
        }

        setTasks(tasksCopy);
      });
    } else {
      setTasks([]);
    }
  }, [user]);

  const renderItem = ({ item }) => (
    <TaskTwo
      item={item}
    />
  );

  return (
    <View style={styles.container}>
          <FlatList
            data={tasks}
            initialNumToRender={5}
            windowSize={4}
            renderItem={renderItem}
            keyExtractor={item => item.id}
          />
    </View>
  );
}

已尝试的解决方案

  • 更新1:将优先级更新函数移至Task组件内并移除useCallback,不再作为props传递,但点击时仍会重渲染
  • 更新2:添加了keyExtractor,并在memo化的Task组件中加入自定义相等函数,问题依旧存在

请问我哪里操作有误?如何阻止点击优先级复选框时整个FlatList重渲染?

内容的提问来源于stack exchange,提问作者Lloyd Rajoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 02:25:17