Redux工具包:如何调用异步函数,然后在一个reducer内调度动作

gab6jxml  于 2023-01-26  发布在  其他
关注(0)|答案(1)|浏览(156)

我在学习还原工具包
我想要达到的目标:启动应用程序时,运行check()函数,通过getCredentials检索保存的凭据,如果存在(!= null),则使用这些凭据登录,如果不显示登录屏幕(当isAuthenticated === false时,登录屏幕可见)
出现以下错误:

Require cycle: state\reducers\authSlice.ts -> state\store.ts -> state\reducers\authSlice.ts

Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle.        
 ERROR  TypeError: undefined is not an object (evaluating '_authSlice.default.reducer')

如果我注解掉store.dispatch,那么代码运行时不会出错。
下面是代码:
store.tsx

import { configureStore } from "@reduxjs/toolkit";
import authSlice from "./reducers/authSlice";

export const store = configureStore({
    reducer: {
        auth: authSlice.reducer
    }
});

export async function getStore(){
    return store;
}

setImmediate(()=>{
    store.dispatch(authSlice.actions.check());
})

export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

authSlice.tsx

import { createSlice } from '@reduxjs/toolkit';
import type { PayloadAction } from '@reduxjs/toolkit'
import { store } from '../store';
import { isAuthenticated, login } from '../../api/auth';
import { getCredentials, saveCredentials } from '../../storage/auth';
import { Credentials } from '../../interfaces/auth';

interface AuthState {
    isAuthenticated?: boolean
    username?: string
}

const initialState: AuthState = {
    isAuthenticated: undefined,
    username: undefined
}

const authSlice = createSlice({
    name: "auth",
    initialState,
    reducers: {
        check(state){
            if (state.isAuthenticated == undefined){
                getCredentials().then(auth=>{
                    if (auth){
                        login(auth).then(()=>{
                            store.dispatch(authSlice.actions.loginSuccess(auth))
                        })
                    } else {
                        store.dispatch(authSlice.actions.unauthenticated())
                    }
                })
            }
        },
        loginSuccess(state,action: PayloadAction<Credentials>){
            state.username = action.payload.username;
            state.isAuthenticated = true;
        },
        unauthenticated(state){
            state.isAuthenticated = false;
        },
    },
});

export default authSlice;

有些人说从reducer调用store.dispatch是一个反模式,但是我应该如何实现同样的逻辑呢?

2j4z5cfb

2j4z5cfb1#

还原剂必须是纯净的,这意味着(除其他外)两件事:

  • reducer不允许有副作用(不调用getCredentialslogin,通常根本没有异步逻辑)。
  • Reducer无法分派动作

你在这里遗漏了很多基础知识,所以我建议你也许可以遵循官方的Redux Essentials Tutorial,阅读一下你应该如何处理副作用之类的事情,这种逻辑在reducer中是没有位置的。

相关问题