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使用错误或环境问题导致,寻求解决方案。
问题原因分析
- 空依赖数组的问题:
fetchQuizz是异步函数,调用后不会立刻返回数据。useEffect执行时,listeQuestion还是初始的空数组,所以setQuestionEnCours(listeQuestion[0])设置的是undefined,后续数据获取完成后,组件重新渲染但useEffect不会再执行(空依赖只执行一次)。 - 无依赖数组的问题:不带依赖数组的useEffect会在每次组件渲染后执行,而
fetchQuizz中调用setListeQuestion会触发组件重新渲染,因此形成无限循环。 - 依赖
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
相关产品推荐
相关产品推荐

