我熟悉react hooks,我发现使用useEffect非常容易,thunk很难处理,我可以只使用useEffect和axios并将结果分派到商店而不使用createAsyncThunk吗?使用它比 useEffect 有什么主要的性能优势吗?
创建AsyncThunk:
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}));
}, []);
这两种设置本质上是相似的。您可以使用两种方法做同样的事情。
如果代码与您在此处编写的代码完全相同,则
createAsyncThunk
方法有一个主要优点,因为它会 catch
API 调用中发生的任何错误。它将通过调度 fetchUserById.rejected
操作而不是 fetchUserById.fulfilled
操作来响应这些错误。您的减速器没有响应 rejected
的情况,这很好。错误仍然被捕获。使用您的 useEffect
,您将面临“Promise 中未捕获的错误”错误的风险。
现在您当然可以自行
catch
纠正错误。您还可以在效果开始时执行 dispatch
pending
操作。但是,一旦您开始这样做,相比之下,createAsyncThunk
可能会感觉容易得多,因为它会自动调度 pending
、fulfilled
和 rejected
操作。
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 })
);
}, []);
不返回
response.data
,只需返回 api 调用而不等待。这样你就有了已完成、已拒绝状态。
您的问题是您需要这些数据做什么?仅在这个组件中还是在多个组件中?您也可以使用 context api 来在组件之间实现更高的数据共享,但说实话,如果您是 React 的初学者,我会在介绍 redux 之前了解 hooks 并做出很好的反应。通常生产应用程序(不是说 100% 但大多数)使用某种异步状态管理。您还可以研究react-query作为如何处理异步内容的另一个选项。
琳达·派斯特是正确的。 只是为了进一步扩展您问题的答案,另一个非常流行的选项是TanStack Query(React Query)。它可以满足您的要求:
const { isLoading, error, data } = useQuery(['repoData'], () =>
fetch('https://api.github.com/repos/tannerlinsley/react-query').then(res =>
res.json()
)
)
repoData
中的缓存,类似于 RTKQ。isLoading, error, data
返回给您,就像 RTKQ 一样。axios
或 fetch
或任何非 RESTful 请求。与繁琐的thunk相比,thunk的灵活性、高内聚性、异步转同步的书写方式确实非常出色。您通常希望使用 hooks 而不是 thunk 来处理异步,然后直接更新到存储。这是因为你混淆了双方的责任:
Thunk 处理应用模型层的业务,该层通常依赖于多个组件。 ⚠️这里所说的业务不仅仅是数据,还包括pending、fulfilled、redirected或者其他状态等流程。
而hooks只能为单个组件提供这些状态和数据,除非你写各种上下文,但是这还是比thunk的写法不太友好
所以原则是,你首先需要分析业务是否是模型级的、公共的,其数据/流程将来可能会依赖于多个组件。一旦完成,您就不应该厌倦将其添加到 thunk 中。否则,你应该使用钩子