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

React Native中useEffect执行结果异常问题求助

React Native useEffect数据获取不稳定问题解决
import { View, Text, StyleSheet, Pressable, Button, ActivityIndicator, Alert, FlatList } from 'react-native';
import { useEffect, useState } from 'react';
import { supabase } from '../lib/supabase';
import { useAuth } from '../providers/AuthProvider';
import { Quizz } from '../types/db'
import { Stack } from 'expo-router';

export default function dailyQuizz() {
    const [listeQuestion, setListeQuestion] = useState<Quizz[]>([]);
    const { user } = useAuth();
    const [selected, setSelected] = useState('');
    const [score, setScore] = useState(0);
    const [questionEnCours, setQuestionEnCours] = useState<Quizz>();

    
    const fetchQuizz = async () => {
        console.log('Fetching....');
            
        let { data, error } = await supabase.from('questions').select('*').limit(3).returns<Quizz[]>();

        if (error) {
            Alert.alert('Error fetching data');
            console.log(error);
        }
        if(data){
            setListeQuestion(data);           
        }

    };
    useEffect(() => {
        fetchQuizz();
        setQuestionEnCours(listeQuestion[0]) ;
        console.log(listeQuestion);
    },[])

   /*const shuffleList:quizzFunction = (array) => {
       console.log('preshuffle  ' + array)
       array.sort(() => Math.random() - 0.5);
       console.log('shuffle' + array)
   }


   const shuffle = (array: []) => {
       array.sort(() => Math.random() - 0.5);
       console.log('shuffle' + array)
       return array;
   }*/


    return (
        <View>
            <Stack.Screen options={{ title: questionEnCours?.question }} />
            <Text> { questionEnCours?.question }</Text>
            {/*< FlatList
                data={questionEnCours?.reponses}
                renderItem={({ item }) => (
                    <Pressable onPress={() => setSelected(item)} key={item} style={styles.optionContainer}>
                        <Text>{item}</Text>
                    </Pressable>

                )} /> */}

        </View>

    );
}

问题现象

我正在开发一款移动端答题程序,遇到useEffect数据返回不稳定的问题:

  • 用空依赖数组时,listeQuestion始终显示空数组,无法正确设置当前问题
    useEffect(() => {
            fetchQuizz();
            setQuestionEnCours(listeQuestion[0]) ;
            console.log(listeQuestion);
        },[])
    
  • 用无依赖数组时,能获取正确数据,但组件会陷入无限循环
    useEffect(() => {
            fetchQuizz();
            setQuestionEnCours(listeQuestion[0]) ;
            console.log(listeQuestion);
        })
    
  • 用**依赖questionEnCours**时,结果随机(有时正确有时为空),且未做任何代码修改(注:代码中存在拼写错误questionEncours)
    useEffect(() => {
            fetchQuizz();
            setQuestionEnCours(listeQuestion[0]) ;
            console.log(listeQuestion);
        },[questionEncours])
    

刚接触React Native,怀疑是useEffect使用错误或环境问题导致,寻求解决方案。

问题原因分析

  1. 空依赖数组的问题:fetchQuizz是异步函数,调用后不会立刻返回数据。useEffect执行时,listeQuestion还是初始的空数组,所以setQuestionEnCours(listeQuestion[0])设置的是undefined,后续数据获取完成后,组件重新渲染但useEffect不会再执行(空依赖只执行一次)。
  2. 无依赖数组的问题:不带依赖数组的useEffect会在每次组件渲染后执行,而fetchQuizz中调用setListeQuestion会触发组件重新渲染,因此形成无限循环。
  3. 依赖questionEnCours的问题:首先存在拼写错误(questionEncours应为questionEnCours),其次逻辑错误——每次questionEnCours变化就重新触发数据请求,导致数据获取和状态更新的逻辑混乱。

解决方法

可以通过两种方式修正:

方法一:在fetchQuizz中直接设置当前问题

修改fetchQuizz函数,当成功获取数据后,直接将第一个问题赋值给questionEnCours:

const fetchQuizz = async () => {
    console.log('Fetching....');
        
    let { data, error } = await supabase.from('questions').select('*').limit(3).returns<Quizz[]>();

    if (error) {
        Alert.alert('Error fetching data');
        console.log(error);
    }
    if(data){
        setListeQuestion(data);
        // 直接设置第一个问题
        setQuestionEnCours(data[0]);
    }
};

// 保持空依赖数组,只在组件挂载时执行一次
useEffect(() => {
    fetchQuizz();
},[])

方法二:监听listeQuestion的变化来设置当前问题

保留原fetchQuizz,添加一个新的useEffect,当listeQuestion更新时自动设置第一个问题:

const fetchQuizz = async () => {
    console.log('Fetching....');
        
    let { data, error } = await supabase.from('questions').select('*').limit(3).returns<Quizz[]>();

    if (error) {
        Alert.alert('Error fetching data');
        console.log(error);
    }
    if(data){
        setListeQuestion(data);           
    }
};

// 组件挂载时触发一次数据请求
useEffect(() => {
    fetchQuizz();
},[])

// 当listeQuestion变化时,设置第一个问题
useEffect(() => {
    if(listeQuestion.length > 0){
        setQuestionEnCours(listeQuestion[0]);
        console.log(listeQuestion);
    }
}, [listeQuestion])

额外优化建议

  • 可以添加加载状态,在数据获取过程中显示ActivityIndicator,提升用户体验;
  • 注意questionEnCours可能为undefined,渲染时尽量使用可选链?.避免报错;
  • 修复代码中注释的shuffle函数类型问题,确保类型定义正确。

内容的提问来源于stack exchange,提问作者Mathieu Françoise

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:24:54