Redux 中异步请求数据时发送多 Action 方法
Redux 中异步请求数据时发送多 Action 的方法有以下几种:
- 使用 Redux Thunk 中间件,它可以让你在 Redux Store 中分发一个函数,而不是一个对象。这个函数可以接收 dispatch 和 getState 作为参数,并在函数内部执行异步操作,然后根据异步操作的结果分发不同的 Action。
- 使用 Redux Saga 中间件,它可以让你在 Redux Store 中分发一个特殊的 Action,称为 Saga Action。这个 Action 会被 Redux Saga 捕获,并执行一个生成器函数,称为 Saga。Saga 可以使用一些特殊的指令,称为 Effect,来执行异步操作,并根据异步操作的结果分发不同的 Action。
- 使用 Redux Toolkit 库提供的 createAsyncThunk 函数,它可以让你创建一个特殊的 Action 创建器,称为 Thunk Action 创建器。这个创建器会返回一个 Thunk Action,即一个带有 payloadCreator 和 typePrefix 属性的函数。当这个 Thunk Action 被分发时,它会执行 payloadCreator 函数,并根据 payloadCreator 函数的返回值(通常是一个 Promise)分发不同的 Action,这些 Action 的类型都会带有 typePrefix 前缀。
- Redux-Thunk 和 Redux-Saga 结合: 有时我们可以将 Redux-Thunk 和 Redux-Saga 结合使用。可以使用 Redux-Thunk 来处理一些简单的异步操作,而使用 Redux-Saga 来处理复杂的异步操作,或者在项目中逐步迁移到 Redux-Saga。
以下是一些示例代码:
- 使用 Redux Thunk 中间件:
// action types const FETCH_TODOS_REQUEST = 'FETCH_TODOS_REQUEST'; const FETCH_TODOS_SUCCESS = 'FETCH_TODOS_SUCCESS'; const FETCH_TODOS_FAILURE = 'FETCH_TODOS_FAILURE'; // action creators const fetchTodosRequest = () => ({ type: FETCH_TODOS_REQUEST }); const fetchTodosSuccess = todos => ({ type: FETCH_TODOS_SUCCESS, payload: todos }); const fetchTodosFailure = error => ({ type: FETCH_TODOS_FAILURE, payload: error }); // thunk action creator const fetchTodos = () => async (dispatch, getState) => { dispatch(fetchTodosRequest()); try { const response = await fetch('/api/todos'); const todos = await response.json(); dispatch(fetchTodosSuccess(todos)); } catch (error) { dispatch(fetchTodosFailure(error)); } }; // reducer const initialState = { loading: false, data: [], error: null, }; const todosReducer = (state = initialState, action) => { switch (action.type) { case FETCH_TODOS_REQUEST: return { ...state, loading: true }; case FETCH_TODOS_SUCCESS: return { ...state, loading: false, data: action.payload }; case FETCH_TODOS_FAILURE: return { ...state, loading: false, error: action.payload }; default: return state; } };
- 使用 Redux Saga 中间件:
// action types const FETCH_TODOS_REQUEST = 'FETCH_TODOS_REQUEST'; const FETCH_TODOS_SUCCESS = 'FETCH_TODOS_SUCCESS'; const FETCH_TODOS_FAILURE = 'FETCH_TODOS_FAILURE'; // action creators const fetchTodosRequest = () => ({ type: FETCH_TODOS_REQUEST }); const fetchTodosSuccess = todos => ({ type: FETCH_TODOS_SUCCESS, payload: todos }); const fetchTodosFailure = error => ({ type: FETCH_TODOS_FAILURE, payload: error }); // saga action creator const fetchTodosSaga = () => ({ type: 'FETCH_TODOS_SAGA' }); // saga function* fetchTodos() { try { const response = yield call(fetch, '/api/todos'); const todos = yield call([response, 'json']); yield put(fetchTodosSuccess(todos)); } catch (error) { yield put(fetchTodosFailure(error)); } } // root saga function* rootSaga() { yield takeEvery('FETCH_TODOS_SAGA', fetchTodos); } // reducer const initialState = { loading: false, data: [], error: null, }; const todosReducer = (state = initialState, action) => { switch (action.type) { case FETCH_TODOS_REQUEST: return { ...state, loading: true }; case FETCH_TODOS_SUCCESS: return { ...state, loading: false, data: action.payload }; case FETCH_TODOS_FAILURE: return { ...state, loading: false, error: action.payload }; default: return state; } };
- 使用 Redux Toolkit 库提供的 createAsyncThunk 函数:
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; // thunk action creator const fetchTodos = createAsyncThunk( 'todos/fetchTodos', async () => { const response = await fetch('/api/todos'); const todos = await response.json(); return todos; } ); // slice const todosSlice = createSlice({ name: 'todos', initialState: { loading: false, data: [], error: null, }, reducers: {}, extraReducers: { [fetchTodos.pending]: (state, action) => { state.loading = true; }, [fetchTodos.fulfilled]: (state, action) => { state.loading = false; state.data = action.payload; }, [fetchTodos.rejected]: (state, action) => { state.loading = false; state.error = action.error; }, }, }); // reducer const todosReducer = todosSlice.reducer;
- Redux-Thunk 和 Redux-Saga 结合: 有时我们可以将 Redux-Thunk 和 Redux-Saga 结合使用。可以使用 Redux-Thunk 来处理一些简单的异步操作,而使用 Redux-Saga 来处理复杂的异步操作,或者在项目中逐步迁移到 Redux-Saga。