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。
查看11道真题和解析