action.payload creactAsyncThunk 未定义

action.payload in creactAsyncThunk is undefined

我正在尝试使用带有 createAsyncThunk 的 axios 从 api 获取用户数据,并希望用户数据通过由createAsyncThunk.

docs

中所述

if the promise resolved successfully, dispatch the fulfilled action with the promise value as action.payload.

但是 action.payload 在 fulfilled action creator 中未定义。

这是我的代码。

/// Create Async Thunk
export const fetchUserData = createAsyncThunk(
  'user/fetchUserData',
  (payload, { dispatch }) => {
    axios
      .get('/user')
      .then(res => {
        console.log(res.data);
        //Used this as a work around for storing data
        dispatch(setUser(res.data));

        return res.data;
       })
      .catch(err => {
        console.error(err);
        return err;
      });
  }
);

/// On Fulfilled
const userSlice = createSlice({
...
  extraReducers:{
  ...
  [fetchUserData.fulfilled]: (state, action) => {
        // Payload is undefined
        state.data = action.payload
      },
  }
}

createAsyncThunk接受两个参数:

  1. type
  2. payloadCreator

其中 payloadCreator 是一个回调函数,它应该 return 一个 promise(包含一些异步逻辑的结果)或一个 (同步)。

因此,您可以这样写:

export const fetchUserData = createAsyncThunk(
  'user/fetchUserData',
  (payload, { dispatch }) => {
    return axios.get('/user'); // Return a promise
  }
);

export const fetchUserData = createAsyncThunk(
  'user/fetchUserData',
  async (payload, { dispatch, rejectWithValue }) => {
    try {
      const response = await axios.get('/user')
      return response // Return a value synchronously using Async-await
    } catch (err) {
      if (!err.response) {
        throw err
      }
      return rejectWithValue(err.response)
    }
  }
);

@Ajeet Shah 回答的补充:

根据 to the documentation 被拒绝的承诺必须 return

  • 一个Error-instance,如new Error(<your message>)
  • 普通值,例如描述性字符串,
  • RejectWithValue return thunkAPI.rejectWithValue()

对于前两个选项,我还没有测试最后一个选项,有效载荷也将由 undefined,但会给出一个包含您拒绝的消息的 error 参数。

看这个例子:

const loginAction = createAsyncThunk(
  "user/login",
  (payload, { getState }) => {
    const { logged_in, currentRequestId, lastRequestId } = getState().login;

    // Do not login if user is already logged in
    if (logged_in) {
      return Promise.reject(new Error(Cause.LoggedIn));
    }

    // Do not login if there is a pending login request
    else if (lastRequestId != null && lastRequestId !== currentRequestId) {
      return Promise.reject(new Error(Cause.Concurrent));
    }

    // May as well try logging in now...
    return AccountManager.login(payload.email, payload.password);
  }
);