Redux createAsyncThunk 与 useEffect 钩子

时间:2021-04-11 00:05:34

标签: javascript reactjs redux react-redux

我熟悉 React 钩子,我发现使用 useEffect 真的很容易,thunk 很难处理,我可以只使用 useEffect 和 axios 并将结果发送到商店而不使用 createAsyncThunk 吗?与 useEffect 相比,使用它有什么主要的性能优势吗?

createAsyncThunk:

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

// First, create the thunk
const fetchUserById = createAsyncThunk(
  'users/fetchByIdStatus',
  async (userId, thunkAPI) => {
    const response = await userAPI.fetchById(userId)
    return response.data
  }
)

// Then, handle actions in your reducers:
const usersSlice = createSlice({
  name: 'users',
  initialState: { entities: [], loading: 'idle' },
  reducers: {
    // standard reducer logic, with auto-generated action types per reducer
  },
  extraReducers: {
    // Add reducers for additional action types here, and handle loading state as needed
    [fetchUserById.fulfilled]: (state, action) => {
      // Add user to the state array
      state.entities.push(action.payload)
    }
  }
})

// Later, dispatch the thunk as needed in the app
dispatch(fetchUserById(123))

使用效果:

import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux'
import { userAPI } from './userAPI'
import axios from 'axios';
 
function App() {  
const dispatch = useDispatch()
useEffect(() => {
axios
  .get(userAPI)
  .then(response => dispatch({type:'fetchUsers',payload:response.data}));
    }, []);

2 个答案:

答案 0 :(得分:3)

这两种设置本质上是相似的。你可以用这两种方法做同样的事情。

使用与您在此处编写的代码完全相同的代码,createAsyncThunk 方法有一个主要优势,因为它会 catch API 调用中发生的任何错误。它将通过调度 fetchUserById.rejected 操作而不是 fetchUserById.fulfilled 操作来响应这些错误。您的减速器没有响应 rejected 的情况,这很好。错误仍然被捕获。使用您的 useEffect,您将面临“未捕获的 Promise 错误”错误的风险。

现在您当然可以自行catch 处理错误。您还可以在效果开始时 dispatch 一个 pending 操作。但是一旦您开始这样做,相比之下 createAsyncThunk 可能会感觉容易得多,因为它会自动分派 pendingfulfilledrejected 操作。

useEffect(() => {
  dispatch({ type: "fetchUsers/pending" });
  axios
    .get(userAPI)
    .then((response) =>
      dispatch({ type: "fetchUsers", payload: response.data })
    )
    .catch((error) =>
      dispatch({ type: "fetchUsers/rejected", payload: error.message })
    );
}, []);

答案 1 :(得分:1)

不返回 response.data 而是返回没有等待的 api 调用。这样你就有了已完成、已拒绝的状态。

至于你的问题是你需要这些数据做什么?只是在这个组件中还是超过 1 个组件?您也可以使用上下文 api 来在组件之间更好地共享数据,但老实说,如果您是 react 的初学者,我会在您引入 redux 之前了解钩子并做出很好的反应。通常生产应用程序,不是说 100%,而是大多数,使用某种带有异步的状态管理。您也可以将 react-query 作为如何处理异步内容的另一种选择。