调用useDispatch()[SOLVED]后React Redux状态未更改



已解决

我正在尝试在基于web的游戏中使用更新版本的react reduxv8.0.2来保持应用程序中的状态,而不必在导航调用之间传递状态。

不幸的是,我遇到了一个问题,玩家状态第一次初始化,但在调用useDispatch()方法后,最终状态没有更新。我试着在网上到处寻找,但目前的解决方案都没有真正解决我的问题。

我甚至强迫我的功能组件重新发布,这仍然只是返回我的播放器的初始状态,而不是我期望的更新状态。有人能帮我弄清楚我在这里缺了什么吗。它一定是一些在redux表单/文档中没有讨论过的小东西。TIA!

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,
},
})

选择.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; // delay in ms
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) => {
// add new player to db
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});
// set in redux as well****
// 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存储中调用setInitreducer,然后记录新状态。我也知道,尝试在之后直接记录状态并不总是反映最新的数据,但我尝试过在组件中添加状态更改,然后记录玩家状态,我只是再次获得相同的数据。没有什么变化。

setInit: (state,action) => {
state = action.payload;
},

这没有任何作用,它只是替换了局部变量state,但Redux不可能看到这一点。您应该更改状态,或者返回一个新状态。在您的情况下,返回action.payload应该有效。

请参阅https://redux-toolkit.js.org/usage/immer-reducers#resetting-并替换状态

最新更新