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

Redux状态更新成功但对应React组件未重新渲染该如何解决?

问题原因

原始代码的核心问题

你在forEach循环中使用异步请求获取单条宝可梦数据,forEach不会等待async回调执行完成,会直接执行后续的dispatch逻辑,此时你传给dispatch的pokemonsArray是空数组。后续所有请求完成后你只是对原数组执行push操作,没有修改数组的引用地址,Redux默认通过引用对比判断状态是否变化,因此不会触发组件重新渲染。
当你切换路由再切回时,PokemonsDisplay组件重新挂载,useSelector会读取此时已经被push完所有数据的数组内容,所以列表能正常显示。

后续修改后action无法触发的问题

你写的initPokemons是Redux thunk格式的action创建函数,必须传给dispatch执行才能生效,你直接调用initPokemons(pokemons)只是生成了一个待执行的函数,没有真正发送action到reducer。同时你把异步逻辑放到了fetchEverything中,这个函数不是thunk,拿不到dispatch方法,自然无法触发状态更新。

修复方案

1. 替换forEach为Promise.all等待所有异步请求完成

不要用forEach处理批量异步请求,改用map生成所有请求的Promise数组,通过Promise.all等待全部请求完成后再生成完整的宝可梦数组,保证dispatch时拿到的是完整数据,且是全新的数组引用。

2. 修正后的完整代码

// pokemonsReducer.js
import getPokemons from '../services/pokemons';
import axios from 'axios';
import { loadPokemonsFromLS, savePokemonsList } from '../utils/localStoragePokemons';

const pokemonsReducer = (state = [], action) => {
    switch(action.type){
        case 'INIT_POKEMONS':
            // 返回全新数组,确保Redux检测到状态变更
            return [...action.payload.pokemons];
        default:
            return state;
    };
};

export const fetchPokemons = (limit, offset) => {
    return async dispatch => {
        try {
            const pokemons = loadPokemonsFromLS(limit, offset);
            dispatch({
                type: 'INIT_POKEMONS',
                payload: { pokemons }
            });
        } catch (error) {
            const pokemonsData = await getPokemons.getPokemons(limit, offset);
            // 生成所有单条宝可梦请求的Promise数组
            const pokemonRequests = pokemonsData.results.map(r => axios.get(r.url));
            // 等待所有请求完成
            const pokemonResponses = await Promise.all(pokemonRequests);
            // 组装完整宝可梦数组
            const pokemonsArray = pokemonResponses.map(res => res.data);
            // 组装本地存储用的对象
            const pokemonsObject = pokemonsArray.reduce((acc, cur, index) => {
                acc[index] = cur;
                return acc;
            }, {});
            savePokemonsList(limit, offset, pokemonsObject);
            dispatch({
                type: 'INIT_POKEMONS',
                payload: { pokemons: pokemonsArray }
            });
        }
    };
};

export default pokemonsReducer;

3. 原有组件调用逻辑无需修改

保留App.js中原来的dispatch(fetchPokemons(limit, offset))调用即可,你后续写的fetchEverything不符合thunk规范,直接废弃不用。

内容的提问来源于stack exchange,提问作者pabloF

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 16:06:03