将 Slice.js 文件转换为 ts(redux 工具包)时出现类型错误

时间:2021-03-15 06:57:17

标签: reactjs typescript redux-toolkit

我刚刚使用 js 文件创建了我的示例 Redux 工具包。现在我正在尝试将它们转换为打字稿。现在修复了一些错误。但我不知道如何解决下面的两个错误。

  1. 类型“void”上不存在属性“name”。 <<<< 也适用于电子邮件、密码...和令牌
  2. 计算属性名称的类型必须为“字符串”、“数字”、“符号”或“任意”<<<< for signupUser.fulfilled、signupUser.pending...等等

请参考我在下面代码中的评论,请帮助我解决问题

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


export interface UserState {
  username: string;
  email: string;
  isFetching: boolean;
  isSuccess: boolean;
  isError: boolean;
  errorMessage: string;
}

interface check {
  name: string;
  email: string;
  password: string;
}

const initialState: UserState = {
  username: "",
  email: "",
  isFetching: false,
  isSuccess: false,
  isError: false,
  errorMessage: "",
}



export const signupUser = createAsyncThunk(
  'users/signupUser',
// 
// 
// async ({ name, email, password} ... <<<  This is the problem 1. 
//

  async ({ name, email, password }, thunkAPI) => {
    try {
      const response = await fetch(
        'https://mock-user-auth-server.herokuapp.com/api/v1/users',
        {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            name,
            email,
            password,
          }),
        },
      );
      const data = await response.json();
      console.log('data', data);

      if (response.status === 200) {
        localStorage.setItem('token', data.token);
        return { ...data, username: name, email };
      }
      return thunkAPI.rejectWithValue(data);
    } catch (e) {
      console.log('Error', e.response.data);
      return thunkAPI.rejectWithValue(e.response.data);
    }
  },
);

export const loginUser = createAsyncThunk(
  'users/login',
  async ({ email, password }, thunkAPI) => {
    try {
      const response = await fetch(
        'https://mock-user-auth-server.herokuapp.com/api/v1/auth',
        {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            email,
            password,
          }),
        },
      );
      const data = await response.json();
      console.log('response', data);
      if (response.status === 200) {
        localStorage.setItem('token', data.token);
        return data;
      }
      return thunkAPI.rejectWithValue(data);
    } catch (e) {
      console.log('Error', e.response.data);
      thunkAPI.rejectWithValue(e.response.data);
    }
  },
);

export const fetchUserBytoken = createAsyncThunk(
  'users/fetchUserByToken',
  async ({ token }, thunkAPI) => {
    try {
     const response = await fetch(
        'https://mock-user-auth-server.herokuapp.com/api/v1/users',
        {
          method: 'GET',
          headers: {
            Accept: 'application/json',
            Authorization: token,
            'Content-Type': 'application/json',
          },
        },
      ); 
      /* test case for Axios
      const response = await axios.get(
        'https://mock-user-auth-server.herokuapp.com/api/v1/users',
        {
          headers: {
            Accept: 'application/json',
            Authorization: token,
            'Content-Type': 'application/json',
          },
        },
      );
        */
      const data = await response.json();
      console.log('data', data, response.status);

      if (response.status === 200) {
        return { ...data };
      }
      return thunkAPI.rejectWithValue(data);
    } catch (e) {
      console.log('Error', e.response.data);
      return thunkAPI.rejectWithValue(e.response.data);
    }
  },
);

export const userSlice = createSlice({
  name: 'user',
  initialState: {
    username: '',
    email: '',
    isFetching: false,
    isSuccess: false,
    isError: false,
    errorMessage: '',
  },
  reducers: {
    clearState: state => {
      state.isError = false;
      state.isSuccess = false;
      state.isFetching = false;

      return state;
    },
  },
////
//// [signupUser.fulfilled] ... <<<< this is the problem 2.
////
////
  extraReducers: {
    [signupUser.fulfilled]: (state, { payload }) => {
      console.log('payload', payload);
      state.isFetching = false;
      state.isSuccess = true;
      state.email = payload.user.email;
      state.username = payload.user.name;
    },
    [signupUser.pending]: state => {
      state.isFetching = true;
    },
    [signupUser.rejected]: (state, { payload }) => {
      state.isFetching = false;
      state.isError = true;
      state.errorMessage = payload.message;
    },
    [loginUser.fulfilled]: (state, { payload }) => {
      state.email = payload.email;
      state.username = payload.name;
      state.isFetching = false;
      state.isSuccess = true;
      return state;
    },
    [loginUser.rejected]: (state, { payload }) => {
      console.log('payload', payload);
      state.isFetching = false;
      state.isError = true;
      state.errorMessage = payload.message;
    },
    [loginUser.pending]: state => {
      state.isFetching = true;
    },
    [fetchUserBytoken.pending]: state => {
      state.isFetching = true;
    },
    [fetchUserBytoken.fulfilled]: (state, { payload }) => {
      state.isFetching = false;
      state.isSuccess = true;

      state.email = payload.email;
      state.username = payload.name;
    },
    [fetchUserBytoken.rejected]: state => {
      console.log('fetchUserBytoken');
      state.isFetching = false;
      state.isError = true;
    },
  },
});

export const { clearState } = userSlice.actions;

export const userSelector = (state: { user: UserState}) => state.user;

1 个答案:

答案 0 :(得分:1)

您需要为放入的参数定义类型。如果您只想输入第一个参数并且可以使用 thunkAPI 的默认值,则可以使用

export const signupUser = createAsyncThunk(
  'users/signupUser',
  async ({ name, email, password }: ArgumentType, thunkAPI) => {

否则,您必须按照 https://redux-toolkit.js.org/usage/usage-with-typescript#createasyncthunk

中的说明声明泛型参数
const fetchUserById = createAsyncThunk<
  // Return type of the payload creator
  MyData,
  // First argument to the payload creator
  number,
  {
    dispatch: AppDispatch
    state: State
    extra: {
      jwt: string
    }
  }
>('users/fetchById', async (userId, thunkApi) => {

对于问题 #2,请注意我们不鼓励使用 extraReducers 的对象映射表示法,因为它通常不太安全,并且在 TypeScript 中不起作用。请使用 https://redux-toolkit.js.org/api/createSlice#the-extrareducers-builder-callback-notation

中所述的构建器符号