React Native调用nextQuestion时questions数组异常变更问题
问题描述
每次调用nextQuestion函数时,questions数组都会发生变化,组件函数仿佛被重新执行,但currentQuestion并未重置。多次打印category可确认该现象。
相关代码
Test组件代码
import React, { useState } from 'react'; import { useLocalSearchParams } from "expo-router"; import { COLORS } from "../constants"; import { View, Text, Image, Button, StyleSheet, SafeAreaView } from "react-native"; import { requestQuestions } from "../constants/support"; import Header from '../constants/testHeader'; const Test = () => { const { category } = useLocalSearchParams(); let questions = requestQuestions(category); const [currentQuestion, setCurrentQuestion] = useState(0); console.log(category) const nextQuestion = () => { const nextIndex = (currentQuestion + 1) % questions.length; if (nextIndex === 0) { alert('All question are finished.'); } else { setCurrentQuestion(nextIndex); } }; const { id, img, question, anwsers } = questions[currentQuestion]; console.log(questions.map(obj => Object.values(obj)[0]), currentQuestion) return ( <SafeAreaView style={styles.area}> <Image source={img || { uri: "https://www.liaros-drive.gr/test/images/pic0484.jpg" }} style={styles.image} /> <Text style={styles.title}>{question}</Text> <SafeAreaView style={styles.buttonContainer}> { anwsers && anwsers.map((anwser, index) => ( <Button key={index} title={`${index+1}) (${anwser})`} onPress={nextQuestion} /> )) } </SafeAreaView> </SafeAreaView> ) } export default Test;
support.js代码
import { sampleSize } from 'lodash'; import { questions } from './questions.json'; export const requestQuestions = (category = "random") => { console.log('test') if (category == "random") { return sampleSize(questions, 10) } else { return sampleSize(questions.filter(x => x.category == category), 10) } }
解决方案
核心问题
组件每次渲染(比如调用setCurrentQuestion更新状态时)都会重新执行整个函数,而你直接在组件顶层调用requestQuestions,这个函数里用sampleSize随机抽取题目,导致每次渲染都会生成全新的questions数组,自然会出现数组“变化”的现象。
修复步骤
- 导入
useMemo:在React导入中加入useMemo
import React, { useState, useMemo } from 'react';
- 缓存
questions数组:用useMemo包裹requestQuestions调用,仅当category变化时才重新生成数组
const questions = useMemo(() => requestQuestions(category), [category]);
- 优化状态更新逻辑(可选但推荐):因为
setCurrentQuestion是异步的,用函数式更新确保拿到最新的状态值,避免闭包问题
const nextQuestion = () => { setCurrentQuestion(prev => { const nextIndex = (prev + 1) % questions.length; if (nextIndex === 0) { alert('所有题目已完成'); } return nextIndex; }); };
修复后效果
现在questions数组只会在category改变时重新生成,每次组件渲染时都会使用同一个数组,不会再出现随机变化的情况,currentQuestion也能正确对应到数组中的题目。
内容的提问来源于stack exchange,提问作者Σταθης Τσαρας
相关产品推荐
相关产品推荐

