Redux 中异步 Action 和异步 Reducer 的实现

Redux 是一个流行的 JavaScript 应用程序状态管理库。它可以帮助开发者轻松管理应用程序状态,并提供预测性和可维护性。在 Redux 中,Action 是一个描述发生了什么的简单对象。Reducer 是一个纯函数,用于根据当前状态和 Action 返回新的状态。但是,Redux 中的 Action 和 Reducer 默认是同步的。在某些情况下,需要异步 Action 和异步 Reducer 来处理异步数据流。本文将介绍 Redux 中异步 Action 和异步 Reducer 的实现。

异步 Action

在 Redux 中,异步 Action 是指 Action 本身并不立即返回结果,而是在一段时间后才会返回结果。例如,当从后台服务器获取数据时,可能需要等待一段时间才能得到结果。为了实现异步 Action,可以使用 Redux 中的 redux-thunk 中间件。

安装和配置 redux-thunk

首先,需要安装 redux-thunk 中间件。可以使用 npm 或 yarn 安装:

然后,在 Redux Store 中应用 redux-thunk 中间件。在创建 Store 的代码中引入 applyMiddlewarethunk,并将它们作为参数传递给 createStore 方法:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const store = createStore(rootReducer, applyMiddleware(thunk));

编写异步 Action

在 Redux 中,Action 是一个简单的 JavaScript 对象,它必须具有一个 type 属性来描述 Action 的类型。对于异步 Action,可以将其 type 属性设置为字符串,表示异步 Action 的开始和结束。

例如,假设需要从服务器获取用户数据。可以编写以下异步 Action:

export const FETCH_USER_REQUEST = 'FETCH_USER_REQUEST';
export const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS';
export const FETCH_USER_FAILURE = 'FETCH_USER_FAILURE';

export const fetchUser = (userId) => {
  return (dispatch) => {
    dispatch({ type: FETCH_USER_REQUEST });

    fetch(`https://example.com/api/users/${userId}`)
      .then(response => response.json())
      .then(data => {
        dispatch({
          type: FETCH_USER_SUCCESS,
          payload: data,
        });
      })
      .catch(error => {
        dispatch({
          type: FETCH_USER_FAILURE,
          payload: error.message,
        });
      });
  };
};

在上面的代码中,fetchUser 是一个异步 Action,它接受一个 userId 参数。在 Action 的内部,首先调用 dispatch 方法,将一个带有 FETCH_USER_REQUEST 类型的 Action 分发到 Store 中。然后,使用 fetch 函数从服务器获取用户数据,并在获取成功时将 FETCH_USER_SUCCESS 类型的 Action 分发到 Store 中。如果获取数据失败,则将 FETCH_USER_FAILURE 类型的 Action 分发到 Store 中。

处理异步 Action

异步 Action 与同步 Action 不同,因为它们不会立即返回结果。在异步 Action 中,需要使用 dispatch 方法将 Action 分发到 Store 中,以便 Reducer 可以处理它们。

在上面的异步 Action 中,当调用 fetchUser 方法时,它返回一个函数,而不是简单的 JavaScript 对象。这个函数接受一个 dispatch 参数,并在函数内部使用 dispatch 方法将 Action 分发到 Store 中。

当在组件中调用 fetchUser 方法时,可以通过 dispatch 方法将其分发到 Store 中:

import { connect } from 'react-redux';
import { fetchUser } from '../actions';

const User = ({ user, fetchUser }) => {
  useEffect(() => {
    fetchUser(123);
  }, [fetchUser]);

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
};

const mapStateToProps = (state) => ({
  user: state.user,
});

const mapDispatchToProps = {
  fetchUser,
};

export default connect(mapStateToProps, mapDispatchToProps)(User);

在上面的代码中,fetchUser 方法通过 mapDispatchToProps 函数映射到组件的 props 中。当组件挂载时,调用 useEffect 钩子,并调用 fetchUser 方法,将 userId 传递为参数。在 fetchUser 方法内部,它将 FETCH_USER_REQUEST 类型的 Action 分发到 Store 中,并使用 fetch 函数从服务器获取用户数据。当获取成功时,将 FETCH_USER_SUCCESS 类型的 Action 分发到 Store 中。

异步 Reducer

在 Redux 中,Reducer 是一个纯函数,用于根据当前状态和 Action 返回新的状态。但是,Redux 中的 Reducer 默认是同步的,并且只能处理同步 Action。在某些情况下,需要异步 Reducer 来处理异步数据流。例如,在从后台服务器获取数据时,需要等待一段时间才能得到结果。为了实现异步 Reducer,可以使用 Redux 中的 redux-thunk 中间件。

编写异步 Reducer

在 Redux 中,异步 Reducer 与同步 Reducer 不同,因为它们需要处理异步 Action。为了处理异步 Action,需要在 Reducer 中使用 switch 语句来处理每个 Action 类型。在处理异步 Action 时,需要分别处理 Action 的开始和结束。

例如,假设需要从服务器获取用户数据。可以编写以下异步 Reducer:

import {
  FETCH_USER_REQUEST,
  FETCH_USER_SUCCESS,
  FETCH_USER_FAILURE,
} from '../actions';

const initialState = {
  user: {},
  loading: false,
  error: null,
};

const userReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_USER_REQUEST:
      return {
        ...state,
        loading: true,
        error: null,
      };
    case FETCH_USER_SUCCESS:
      return {
        ...state,
        user: action.payload,
        loading: false,
        error: null,
      };
    case FETCH_USER_FAILURE:
      return {
        ...state,
        loading: false,
        error: action.payload,
      };
    default:
      return state;
  }
};

export default userReducer;

在上面的代码中,userReducer 是一个异步 Reducer。它接受一个名为 state 的参数,并根据 action.type 处理每个 Action 类型。当收到 FETCH_USER_REQUEST 类型的 Action 时,将 loading 属性设置为 true,并将 error 属性设置为 null。当收到 FETCH_USER_SUCCESS 类型的 Action 时,将 user 属性设置为 action.payload,并将 loading 属性设置为 false。当收到 FETCH_USER_FAILURE 类型的 Action 时,将 loading 属性设置为 false,并将 error 属性设置为 action.payload

应用异步 Reducer

在 Redux 中,可以通过 combineReducers 方法将多个 Reducer 合并为一个单一的 Reducer。在创建 Store 的代码中,将合并后的 Reducer 传递给 createStore 方法。

import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import userReducer from './reducers/userReducer';

const rootReducer = combineReducers({
  user: userReducer,
});

const store = createStore(rootReducer, applyMiddleware(thunk));

在上面的代码中,使用 combineReducers 方法将 userReducer 合并到 rootReducer 中,并将 rootReducer 传递给 createStore 方法。

处理异步 Reducer

异步 Reducer 与同步 Reducer 不同,因为它们需要处理异步 Action。在异步 Reducer 中,需要处理每个 Action 类型的开始和结束。在开始时,需要将 loading 属性设置为 true,并将 error 属性设置为 null。在结束时,需要将 loading 属性设置为 false,并将 error 属性设置为 action.payload

总结

在 Redux 中,异步 Action 和异步 Reducer 可以帮助开发者处理异步数据流。异步 Action 可以通过 redux-thunk 中间件实现,而异步 Reducer 可以通过在 Reducer 中处理异步 Action 实现。在处理异步数据流时,需要注意异步 Action 和异步 Reducer 的实现方式,以确保代码的正确性和可维护性。

示例代码:https://github.com/zhongdeming428/async-redux-example

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/658a3587eb4cecbf2df65a94


纠错
反馈