调用useDispatch()后React Redux状态未更新问题【已解决】
Redux状态更新失败问题排查
我在网页游戏中使用React Redux v8.0.2,希望无需在导航调用间传递状态来管理应用内状态,但遇到了问题:player状态首次初始化后,调用useDispatch()方法后最终状态并未更新。我试过网上各种方案都没解决,甚至强制函数组件重渲染,仍只返回player的初始状态,而非预期的更新后状态。
playerSlice.js
import {createSlice} from '@reduxjs/toolkit'; export const playerSlice = createSlice({ name: 'player', initialState: { address: '', cp: 0, created: '', faction: 0, faction_selected: false, games_lost: 0, games_won: 0, online: false, selected_char: 0, selected: { combatType: '', lvl: 0, mgc: 0, str: 0, rng: 0, def: 0 }, time_played: 0, tokens: 10000, total_cp: 0, total_earned: 0, user_name: "" }, reducers: { setInit: (state,action) => { state = action.payload; }, setCP: (state,action) => { state.cp += action.payload; }, setFaction: (state,action) => { state.faction = action.payload; }, setGamesLost: (state,action) => { state.games_lost = action.payload; }, setGamesWon: (state,action) => { state.games_won = action.payload; }, setPlayerState: (state,action) => { state = { ...state, ...action.payload } } } }); export const {setInit, setCP, setFaction, setGamesLost, setGamesWon, setPlayerState} = playerSlice.actions; export const selectPlayer = (state) => state.player; export default playerSlice.reducer;
index.js
import {configureStore} from '@reduxjs/toolkit'; import playerReducer from '../store/playerSlice'; export default configureStore({ reducer: { player: playerReducer, }, })
Selection.js
import Card from './Card'; import React, {useState, useEffect} from 'react'; import '../stylesheet/Selection.css'; import Logo from '../assets/degen age title GNW skull.png'; import KnightTitle from '../assets/knights title.png'; import GoblinTitle from '../assets/goblins title.png'; import WizardTitle from '../assets/wizards title.png'; import ElfTitle from '../assets/elves title.png'; import SorcererShield from '../assets/sorcerers shield item.jpg'; import Weaken from '../assets/weaken item img.jpg'; import Barrage from '../assets/barrage item img.jpg'; import Berserk from '../assets/berserk item img.jpg'; import {db} from '../firebase/firestore'; import {addDoc,collection, serverTimestamp} from 'firebase/firestore'; import { useNavigate, useLocation } from 'react-router-dom'; import {CHAR_RACES} from '../constants'; import {useSelector, useDispatch} from 'react-redux'; import {setInit, selectPlayer} from '../store/playerSlice'; const SCREEN_DELAY = 4000; // 延迟(毫秒) const Selection = () => { const [initScreen, setInitScreen] = useState(true); const player = useSelector(selectPlayer); const dispatch = useDispatch(); const navigate = useNavigate(); const [ready,setReady] = useState(false); const {state} = useLocation(); useEffect(() => { let mounted = true; if(mounted){ setTimeout(() => { setInitScreen(false); },SCREEN_DELAY); } return () => { mounted = false; } },[]); const handleFactionSelect = async (_faction) => { // 将新玩家添加到数据库 const ref = collection(db, 'players'); const playerData = { address: state.address, cp: 0, created: serverTimestamp(), faction: _faction, faction_selected: true, games_lost: 0, games_won: 0, online: true, selected_char: 0, selected: { combatType: 'MELEE', lvl: 200, mgc: 10, str: 59, rng: 30, def: 101 }, time_played: 0, tokens: 10000, total_cp: 0, total_earned: 0, user_name: "someUser393900" } dispatch(setInit({ ...playerData, created: new Date().getTime(), faction: _faction })) console.log({player}); // 同时在redux中设置**** // addDoc(ref,playerData).then(res => { // if(res.id){ // const _faction = CHAR_RACES[playerData.faction]; // dispatch(setInit({ // ...playerData, // created: new Date().getTime(), // faction: _faction // })) // // navigate('/play',{ // // state: { // // player: { // // ...playerData, // // faction: _faction // // } // // } // // }); // navigate('/play'); // } // }).catch(error => { // console.error(error); // }) } return ( <div className='select-main'> {!initScreen ? <div id="main-select" className='fade-in-slow2 select-wrapper'> <h1 className='text-center'>CHOOSE YOUR SIDE</h1> <div className='select-cards'> <Card cardStyle="f1" ability={SorcererShield} desc="Sorcerers Shield" title={WizardTitle} name={1} onClick={handleFactionSelect} /> <Card cardStyle="f3" ability={Berserk} desc="Berserk" title={KnightTitle} name={2} onClick={handleFactionSelect} /> <Card cardStyle="f2" ability={Barrage} desc="Barrage" title={ElfTitle} name={0} onClick={handleFactionSelect} /> <Card cardStyle="f4" ability={Weaken} desc="Weaken" title={GoblinTitle} name={3} onClick={handleFactionSelect} /> </div> </div> : <div className='fade-in-slow sub-select-wrapper flex-just-center'> <div className='cracked'></div> </div> } </div> ) } export default Selection;
我尝试调用Redux store中的setInit reducer后记录新状态,也知道直接在调用后记录状态不一定能反映最新数据,但即使添加组件状态变更来记录player状态,结果仍返回相同的初始数据,没有任何变化。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

