调用useDispatch()后,React Redux状态未更改[已解决]

hjzp0vay  于 2022-11-12  发布在  React
关注(0)|答案(1)|浏览(200)

已解决

我正在尝试在基于Web的游戏中使用react redux v8.0.2的更新版本,以便在应用程序中保持状态,而不必在导航调用之间传递状态。
不幸的是,我遇到了一个问题,即播放器状态第一次被初始化,但在调用useDispatch()方法后,最终状态没有更新。我试着在网上到处寻找,但目前没有一个解决方案真正解决了我的问题。
我甚至强迫我的功能组件重新呈现,但仍然只是返回我的播放器的初始状态,而不是我所期望的更新状态。有人能帮我找出我在这里遗漏了什么吗?这一定是redux forms/docs上没有提到的一些小东西。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,
    },
})

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; // 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存储中调用setInit reducer,然后记录新的状态。我也知道,尝试直接记录状态并不总是反映最新的数据,但我已经尝试过向组件添加状态更改,然后记录播放器状态,我只是再次得到相同的数据。没有任何变化。

bjp0bcyl

bjp0bcyl1#

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

这并没有做任何事情,它只是替换了本地变量state,但是Redux不可能看到这一点。你应该 mutate 状态,或者返回一个新的状态。在你的情况下,返回action.payload应该可以。
请访问https://redux-toolkit.js.org/usage/immer-reducers#resetting-and-replacing-state

相关问题