如何在Redux切片的Reducer中重执行函数以确保随机选不同国家
解决Redux切片中随机选取重复国家的问题
问题分析
你当前的代码仅做了一次判断:如果随机选中的两个国家相同,就不会更新questionOption1和questionOption2,但后续的状态重置(如correctAnswer1等)依然会执行,导致界面可能显示旧选项,或出现两个相同国家的情况。
解决方案
通过循环逻辑确保生成两个不同的随机国家,以下是两种可靠实现方式:
方式一:do-while循环确保国家不同
先随机选中第一个国家,再循环选取第二个国家,直到它与第一个国家不同:
import { createSlice } from "@reduxjs/toolkit"; import { data } from "../data/countries"; const initialState = { countries: data, questionOption1: { image: "", title: "", area: 0, }, questionOption2: { image: "", title: "", area: 0, }, correctAnswer1: true, correctAnswer2: true, correctAnswer1Tick: 0, correctAnswer2Tick: 0, total: 0, }; const countriesSlice = createSlice({ name: "countries", initialState, reducers: { setQuestion1: (state) => { // 随机选取第一个国家 let random1 = state.countries[Math.floor(Math.random() * state.countries.length)]; let random2; // 循环选取第二个国家,直到与第一个不同 do { random2 = state.countries[Math.floor(Math.random() * state.countries.length)]; } while (random1.title === random2.title); // 用title作为唯一标识,避免对象引用判断的潜在问题 // 更新选项状态 state.questionOption1 = { image: random1.image, title: random1.title, area: random1.area, }; state.questionOption2 = { image: random2.image, title: random2.title, area: random2.area, }; // 重置其他状态 state.correctAnswer1 = true; state.correctAnswer2 = true; state.correctAnswer1Tick = 0; state.correctAnswer2Tick = 0; }, }, }); export const countriesActions = countriesSlice.actions; export default countriesSlice.reducer;
方式二:通过索引排除已选国家(效率更高)
先获取第一个国家的索引,再从剩余索引中随机选取第二个,避免重复判断:
import { createSlice } from "@reduxjs/toolkit"; import { data } from "../data/countries"; const initialState = { countries: data, questionOption1: { image: "", title: "", area: 0, }, questionOption2: { image: "", title: "", area: 0, }, correctAnswer1: true, correctAnswer2: true, correctAnswer1Tick: 0, correctAnswer2Tick: 0, total: 0, }; const countriesSlice = createSlice({ name: "countries", initialState, reducers: { setQuestion1: (state) => { const countryCount = state.countries.length; // 选取第一个国家的索引 const index1 = Math.floor(Math.random() * countryCount); // 选取第二个国家的索引,确保不等于index1 let index2; do { index2 = Math.floor(Math.random() * countryCount); } while (index2 === index1); const random1 = state.countries[index1]; const random2 = state.countries[index2]; // 更新选项状态 state.questionOption1 = { image: random1.image, title: random1.title, area: random1.area, }; state.questionOption2 = { image: random2.image, title: random2.title, area: random2.area, }; // 重置其他状态 state.correctAnswer1 = true; state.correctAnswer2 = true; state.correctAnswer1Tick = 0; state.correctAnswer2Tick = 0; }, }, }); export const countriesActions = countriesSlice.actions; export default countriesSlice.reducer;
关键说明
- 用
title(或其他唯一字段)代替对象引用比较:若data数组存在重复对象(概率极低),对象引用===判断可能失效,唯一标识字段更可靠。 - 循环逻辑确保一定会生成两个不同的国家,不会出现跳过更新选项的情况。
- 两种方式均可解决问题,方式二通过索引排除,在国家数量较多时效率略高。
内容的提问来源于stack exchange,提问作者Thecountofs
相关产品推荐
相关产品推荐

