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 安装:
npm install redux-thunk
或
yarn add redux-thunk
然后,在 Redux Store 中应用 redux-thunk
中间件。在创建 Store 的代码中引入 applyMiddleware
和 thunk
,并将它们作为参数传递给 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