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

React Native子组件useEffect未触发问题求助

问题分析:TaskList组件useEffect未触发的原因

问题描述

我开发了一个React Native应用,其中包含TasksScreen页面和其子组件TaskList,目前遇到的问题是:TaskList子组件中用于获取数据的useEffect代码完全没有被调用。但当我将loading/setLoading状态从TasksScreen父组件移到TaskList子组件中时,该逻辑就能正常运行。

相关代码

TasksScreen父组件

export default function TasksScreen() {
  const [loading, setLoading] = useState<boolean>(true);

  const colorScheme = useColorScheme() ?? "light";
  const theme = colorScheme === "dark" ? darkTheme : lightTheme;
  const themeColors = colorStyles[colorScheme];

  const onLoadingChanged = (loading: boolean) => setLoading(loading);

  if (loading) {
    return (
      <View style={theme.loaderContainer}>
        <ActivityIndicator size="large" color={themeColors.primary} />
      </View>
    );
  }

  const selectTask = (task: TaskEntity) => {
    router.push(`/task/${task.id}`);
  };

  return (
    <SafeAreaView style={theme.container}>
      <View
        style={{
          flexDirection: "row",
          justifyContent: "space-between",
          alignItems: "center",
          padding: 16,
          backgroundColor: themeColors.background,
        }}
      >
        <Text type="subtitle">Tasks:</Text>
        <TouchableOpacity style={theme.buttonPrimary} onPress={() => router.push('/task/create')}>
          <Text style={theme.buttonTextPrimary}>Create new task</Text>
        </TouchableOpacity>
      </View>
      <TaskList key="TabsTasklist" setLoading={onLoadingChanged} selectTask={selectTask} />
    </SafeAreaView>
  );
}

TaskList子组件

const TaskList = ({
  setLoading,
  selectTask,
}: {
  setLoading: (loading: boolean) => void;
  selectTask: (task: TaskEntity) => void;
}) => {
  const [tasks, setTasks] = useState<TaskEntity[]>([]);

  const colorScheme = useColorScheme() ?? "light";
  const theme = colorScheme === "dark" ? darkTheme : lightTheme;
  const themeColors = colorStyles[colorScheme];

  useEffect(() => {
    console.log("Fetching tasks!");

    const loadTasks = async () => {
      try {
        const fetchedTasks = await getAllTasks();

        if (fetchedTasks.length === 0) {
          Alert.alert("Error", "Failed to fetch tasks.");
        }
        console.log("Tasks fetched: ", fetchedTasks);

        setTasks(fetchedTasks);
        setLoading(false);
      } catch (error) {
        Alert.alert("Error", "Failed to fetch tasks. Reason: " + error);
      }
    };

    loadTasks();
  });

  return (
    <FlatList
      data={tasks}
      keyExtractor={(item) => item.id}
      renderItem={({ item }) => (
        <TaskListCell entity={item} onPress={selectTask} />
      )}
      contentContainerStyle={theme.listContainer}
      ListEmptyComponent={
        <Text style={theme.emptyText}>No task available!</Text>
      }
    />
  );
};

原因分析

核心问题在于父组件的初始loading状态为true,导致TaskList组件从未被挂载:

  • 父组件中loading的初始值是true,此时会直接返回加载指示器的JSX,不会渲染后续的SafeAreaView和TaskList组件
  • 组件未被挂载,其内部的useEffect自然不会执行,也就不会触发数据请求
  • 当把loading状态移到TaskList内部时,组件会正常挂载,useEffect在组件挂载阶段触发,数据请求逻辑得以执行,之后再通过内部的setLoading控制加载状态,所以功能正常。

解决建议

  • 方案一:将loading状态完全交给子组件管理,父组件不再通过loading条件阻止子组件渲染,而是由子组件内部处理加载状态和UI展示
  • 方案二:如果必须保留父组件的loading状态,需要在父组件挂载时直接触发数据请求,而非依赖子组件的useEffect。比如将数据请求逻辑移到父组件,请求完成后再渲染TaskList。

内容的提问来源于stack exchange,提问作者Bawenang Rukmoko Pardian Putra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 13:45:14