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

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数组,自然会出现数组“变化”的现象。

修复步骤

  1. 导入useMemo:在React导入中加入useMemo
import React, { useState, useMemo } from 'react';
  1. 缓存questions数组:用useMemo包裹requestQuestions调用,仅当category变化时才重新生成数组
const questions = useMemo(() => requestQuestions(category), [category]);
  1. 优化状态更新逻辑(可选但推荐):因为setCurrentQuestion是异步的,用函数式更新确保拿到最新的状态值,避免闭包问题
const nextQuestion = () => {
    setCurrentQuestion(prev => {
        const nextIndex = (prev + 1) % questions.length;
        if (nextIndex === 0) {
            alert('所有题目已完成');
        }
        return nextIndex;
    });
};

修复后效果

现在questions数组只会在category改变时重新生成,每次组件渲染时都会使用同一个数组,不会再出现随机变化的情况,currentQuestion也能正确对应到数组中的题目。

内容的提问来源于stack exchange,提问作者Σταθης Τσαρας

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 21:13:21