带有 Firebase 身份验证的 Redux

Redux with firebase autentication

我正在尝试使用带有 redux 工具包的 redux 为我的 react 添加身份验证 这就是我目前拥有的 我的登录函数创建 createAsyncThunk

 export const signin = createAsyncThunk(
  'authentication/signin',
  async (signinCredentials: userData, { rejectWithValue }) => {
    const { email, password } = signinCredentials;
    await signInWithEmailAndPassword(auth, email, password)
      .then((userCredential) => {
        // Signed in
        const user = userCredential.user;
        return user;
      })
      .catch((error) => {
        console.log(error.message);
        const errorMessage = error.message;
        return rejectWithValue(errorMessage);
      });
  }
);

我有一个 userState 界面,如下所示

  export interface userState {
  user: object | null;
  status: 'idle' | 'loading' | 'failed';
  isAuth: boolean;
  message: string;
}

这是初始状态

 const initialState: userState = {
  user: null,
  status: 'idle',
  isAuth: false,
  message: '',
};

我的授权片是这个 问题是即使我尝试访问 action.payload。我已经用打字稿

标记了错误的区域
export const authSlice = createSlice({
  name: 'authentication',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(signin.pending, (state) => {
        state.status = 'loading';
        state.isAuth = false;
      })
      .addCase(signin.fulfilled, (state, action) => {
        state.status = 'idle';
        state.isAuth = true;
        state.user = action.payload; type void is not assignable to type 'object' | null
      })
      .addCase(signin.rejected, (state, action) => {
        state.status = 'failed';
        state.isAuth = false;
        state.message = action.payload; type 'unknown' is not assignable to type 'string'
      })     
  },
});

一段时间以来,我一直在尝试解决这些问题,但无法弄清楚发生了什么。我已尝试留下尽可能多的信息,但如果您需要更多信息。请告诉我。谢谢

usage-with-typescript#createasyncthunk

我们应该为 createAsyncThunk 提供正确类型的通用参数,并为以下部分或所有字段提供类型声明:

type AsyncThunkConfig = {
  /** return type for `thunkApi.getState` */
  state?: unknown
  /** type for `thunkApi.dispatch` */
  dispatch?: Dispatch
  /** type of the `extra` argument for the thunk middleware, which will be passed in as `thunkApi.extra` */
  extra?: unknown
  /** type to be passed into `rejectWithValue`'s first argument that will end up on `rejectedAction.payload` */
  rejectValue?: unknown
  /** return type of the `serializeError` option callback */
  serializedErrorType?: unknown
  /** type to be returned from the `getPendingMeta` option callback & merged into `pendingAction.meta` */
  pendingMeta?: unknown
  /** type to be passed into the second argument of `fulfillWithValue` to finally be merged into `fulfilledAction.meta` */
  fulfilledMeta?: unknown
  /** type to be passed into the second argument of `rejectWithValue` to finally be merged into `rejectedAction.meta` */
  rejectedMeta?: unknown
}

以便正确推断 action.payload 类型的 case reducer。

例如

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

interface userData {
  email: string;
  password: string;
}

export const signin = createAsyncThunk<{ email: string }, userData, { rejectValue: string }>(
  'authentication/signin',
  async (signinCredentials: userData, { rejectWithValue }) => {
    const { email, password } = signinCredentials;
    try {
      throw new Error('password incorrect');
    } catch (error) {
      return rejectWithValue(error.message);
    }
  },
);

export interface userState {
  user: object | null;
  status: 'idle' | 'loading' | 'failed';
  isAuth: boolean;
  message: string;
}
const initialState: userState = {
  user: null,
  status: 'idle',
  isAuth: false,
  message: '',
};

export const authSlice = createSlice({
  name: 'authentication',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(signin.pending, (state) => {
        state.status = 'loading';
        state.isAuth = false;
      })
      .addCase(signin.fulfilled, (state, action) => {
        state.status = 'idle';
        state.isAuth = true;
        state.user = action.payload;
      })
      .addCase(signin.rejected, (state, action) => {
        state.status = 'failed';
        state.isAuth = false;
        if (action.payload) {
          state.message = action.payload;
        }
      });
  },
});