Redux中间件是位于派发和归约器之间的扩展点,它可以拦截、处理或修改派发的动作,并且可以对派发的动作进行异步处理。中间件提供了一种灵活的机制,可以在Redux应用中处理各种复杂的业务逻辑和副作用。
npm install redux redux-thunk --save
在创建Redux存储(store)之前,需要将Redux Thunk中间件应用到Redux存储中。在创建存储之前,通过applyMiddleware
方法将Redux Thunk中间件传递给createStore
函数。例如:
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const store = createStore(rootReducer, applyMiddleware(thunk));
在上面的示例中,我们将Redux Thunk中间件传递给applyMiddleware
函数,然后将其作为第二个参数传递给createStore
函数。
现在,你可以创建异步的动作创建函数(action creators)了。异步的动作创建函数可以返回一个函数,而不仅仅是一个动作对象。这个函数可以在需要时进行异步操作,并最终派发一个或多个动作。例如:
import axios from 'axios';
export const fetchUser = () => {
return dispatch => {
dispatch({ type: 'FETCH_USER_REQUEST' });
axios.get('https://api.example.com/users')
.then(response => {
dispatch({ type: 'FETCH_USER_SUCCESS', payload: response.data });
})
.catch(error => {
dispatch({ type: 'FETCH_USER_FAILURE', payload: error.message });
});
};
};
在上面的示例中,我们创建了一个fetchUser
的异步动作创建函数。它返回一个函数,该函数接收dispatch
作为参数。在这个函数中,我们首先派发一个FETCH_USER_REQUEST
动作来表示异步操作开始。然后,我们使用axios库发起异步请求,并在请求成功或失败时派发相应的动作。
在组件中使用异步的动作创建函数。你可以在组件中使用connect
函数来连接Redux存储,并将异步的动作创建函数映射为组件的属性。例如:
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { fetchUser } from './actions';
const UserComponent = ({ user, fetchUser }) => {
useEffect(() => {
fetchUser();
}, [fetchUser]);
if (user.loading) {
return Loading...;
}
if (user.error) {
return Error: {user.error};
}
return (
User: {user.name}
Email: {user.email}
);
};
const mapStateToProps = state => {
return {
user: state.user
};
};
export default connect(mapStateToProps, { fetchUser })(UserComponent);
在上面的示例中,我们使用connect
函数将Redux存储中的user
状态映射为组件的属性。我们还将fetchUser
异步动作创建函数映射为组件的属性。在组件加载时,我们使用useEffect
钩子调用fetchUser
函数来发起异步操作。
这样,你就可以使用Redux Thunk中间件来处理异步操作了。当调用异步动作创建函数时,Redux Thunk会将函数作为参数传递给dispatch
方法,并在适当的时候派发动作。在异步操作完成后,你可以在归约器中处理相应的动作来更新状态。
安装:
npm install redux redux-saga --save
在创建Redux存储(store)之前,需要将Redux Saga中间件应用到Redux存储中。在创建存储之前,通过applyMiddleware
方法将Redux Saga中间件传递给createStore
函数。例如:
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from './reducers';
import rootSaga from './sagas';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
sagaMiddleware.run(rootSaga);
在上面的示例中,我们首先创建了一个Redux Saga中间件实例sagaMiddleware
。然后,将其作为参数传递给applyMiddleware
函数,并将其作为第二个参数传递给createStore
函数。最后,我们使用sagaMiddleware.run
方法来运行根Saga。
这样,你就可以使用Redux Saga来处理复杂的异步操作和副作用了。当调用Saga函数时,Redux Saga会自动监听相应的动作,并在适当的时候执行相应的处理逻辑。在处理逻辑中,你可以使用Saga提供的效果函数来处理异步操作、派发动作和控制流程。
创建Saga文件。在Redux Saga中,我们需要创建一个或多个Saga文件来处理异步操作和副作用。Saga文件通常包含一个或多个Generator函数,这些Generator函数被称为Saga。例如,我们创建一个名为userSaga.js
的Saga文件来处理用户相关的异步操作:
import { call, put, takeEvery } from 'redux-saga/effects';
import { FETCH_USER_REQUEST, fetchUserSuccess, fetchUserFailure } from './actions';
import api from './api';
function* fetchUser() {
try {
const user = yield call(api.fetchUser);
yield put(fetchUserSuccess(user));
} catch (error) {
yield put(fetchUserFailure(error.message));
}
}
function* userSaga() {
yield takeEvery(FETCH_USER_REQUEST, fetchUser);
}
export default userSaga;
在上面的示例中,我们定义了一个fetchUser
的Saga函数。在这个Saga函数中,我们使用call
效果调用api.fetchUser
方法来获取用户数据。然后,使用put
效果派发相应的动作,例如fetchUserSuccess
或fetchUserFailure
。最后,我们定义了一个userSaga
根Saga函数,使用takeEvery
效果监听FETCH_USER_REQUEST
动作,并在收到该动作时调用fetchUser
函数。
在根Saga文件中组合Saga。我们需要创建一个根Saga文件,将所有的Saga组合在一起。例如,我们创建一个名为rootSaga.js
的根Saga文件:
import { all } from 'redux-saga/effects';
import userSaga from './userSaga';
import postSaga from './postSaga';
function* rootSaga() {
yield all([
userSaga(),
postSaga(),
]);
}
export default rootSaga;
在上面的示例中,我们使用all
效果将多个Saga函数组合在一起,然后将其导出为根Saga函数。
在组件中使用Saga。你可以在组件中使用connect
函数来连接Redux存储,并在组件加载时调用Saga函数。例如:
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { fetchUserRequest } from './actions';
const UserComponent = ({ user, fetchUserRequest }) => {
useEffect(() => {
fetchUserRequest();
}, [fetchUserRequest]);
if (user.loading) {
return Loading...;
}
if (user.error) {
return Error: {user.error};
}
return (
User: {user.name}
Email: {user.email}
);
};
const mapStateToProps = state => {
return {
user: state.user
};
};
export default connect(mapStateToProps, { fetchUserRequest })(UserComponent);
在上面的示例中,我们使用connect
函数将Redux存储中的user
状态映射为组件的属性。我们还将fetchUserRequest
动作创建函数映射为组件的属性。在组件加载时,我们使用useEffect
钩子调用fetchUserRequest
函数来发起异步操作。
安装:
npm install redux redux-observable rxjs --save
在创建Redux存储(store)之前,需要将Redux Observable中间件应用到Redux存储中。在创建存储之前,通过applyMiddleware
方法将Redux Observable中间件传递给createStore
函数。例如:
import { createStore, applyMiddleware } from 'redux';
import { createEpicMiddleware } from 'redux-observable';
import { rootEpic } from './epics';
import rootReducer from './reducers';
const epicMiddleware = createEpicMiddleware();
const store = createStore(rootReducer, applyMiddleware(epicMiddleware));
epicMiddleware.run(rootEpic);
在上面的示例中,我们首先创建了一个Redux Observable中间件实例epicMiddleware
。然后,将其作为参数传递给applyMiddleware
函数,并将其作为第二个参数传递给createStore
函数。最后,我们使用epicMiddleware.run
方法来运行根Epic。
创建Epic文件。在Redux Observable中,我们需要创建一个或多个Epic文件来处理异步操作和副作用。Epic是一个函数,它接收一个Observable输入流,处理输入流中的动作,并返回一个输出流,该输出流也是一个Observable。例如,我们创建一个名为userEpic.js
的Epic文件来处理用户相关的异步操作:
import { ofType } from 'redux-observable';
import { mergeMap, map, catchError } from 'rxjs/operators';
import { FETCH_USER_REQUEST, fetchUserSuccess, fetchUserFailure } from './actions';
import api from './api';
export const fetchUserEpic = action$ =>
action$.pipe(
ofType(FETCH_USER_REQUEST),
mergeMap(action =>
api.fetchUser().pipe(
map(user => fetchUserSuccess(user)),
catchError(error => {
console.error(error);
return fetchUserFailure(error.message);
})
)
)
);
在上面的示例中,我们定义了一个fetchUserEpic
函数。在这个函数中,我们使用ofType
操作符来过滤输入流中与FETCH_USER_REQUEST
动作类型匹配的动作。然后,使用mergeMap
操作符来处理输入流中的动作,并通过调用api.fetchUser
方法来获取用户数据。通过使用map
操作符,我们将获取到的用户数据转换为fetchUserSuccess
动作。如果在获取用户数据时出现错误,我们使用catchError
操作符来捕获错误,并返回fetchUserFailure
动作。
在根Epic文件中组合Epic。我们需要创建一个根Epic文件,将所有的Epic组合在一起。例如,我们创建一个名为rootEpic.js
的根Epic文件:
import { combineEpics } from 'redux-observable';
import { fetchUserEpic } from './userEpic';
import { fetchPostEpic } from './postEpic';
export const rootEpic = combineEpics(fetchUserEpic, fetchPostEpic);
在上面的示例中,我们使用combineEpics
函数将多个Epic函数组合在一起,并将其导出为根Epic函数。
在组件中使用Epic。你可以在组件中使用connect
函数来连接Redux存储,并在组件加载时调用Epic函数。例如:
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { fetchUserRequest } from './actions';
const UserComponent = ({ user, fetchUserRequest }) => {
useEffect(() => {
fetchUserRequest();
}, [fetchUserRequest]);
if (user.loading) {
return Loading...;
}
if (user.error) {
return Error: {user.error};
}
return (
User: {user.name}
Email: {user.email}
);
};
const mapStateToProps = state => {
return {
user: state.user
};
};
export default connect(mapStateToProps, { fetchUserRequest })(UserComponent);
在上面的示例中,我们使用connect
函数将Redux存储中的user
状态映射为组件的属性。我们还将fetchUserRequest
动作创建函数映射为组件的属性。在组件加载时,我们使用useEffect
钩子调用fetchUserRequest
函数来发起异步操作。
这样,你就可以使用Redux Observable来处理复杂的异步操作和副作用了。当调用Epic函数时,Redux Observable会自动监听相应的
首先,确保你的应用已经安装了redux和redux-promise库。可以使用以下命令进行安装:
npm install redux redux-promise --save
在创建Redux存储(store)之前,需要将Redux Promise中间件应用到Redux存储中。在创建存储之前,通过applyMiddleware
方法将Redux Promise中间件传递给createStore
函数。例如:
import { createStore, applyMiddleware } from 'redux';
import promiseMiddleware from 'redux-promise';
import rootReducer from './reducers';
const store = createStore(rootReducer, applyMiddleware(promiseMiddleware));
在上面的示例中,我们通过applyMiddleware
方法将Redux Promise中间件传递给createStore
函数,以便在创建存储时应用该中间件。
创建Action。在Redux Promise中,我们可以使用Promise对象作为Action的payload。当使用Redux Promise中间件时,它会自动处理Promise对象并根据Promise的状态分发相应的Action。例如,我们创建一个名为fetchUser
的Action来获取用户数据:
export const fetchUser = () => ({
type: 'FETCH_USER',
payload: api.fetchUser() // 返回一个Promise对象
});
在上面的示例中,我们通过调用api.fetchUser
方法来获取用户数据,并将返回的Promise对象作为Action的payload。
创建Reducer。在Reducer中,我们可以使用Redux Promise中间件处理Promise对象的状态,并更新状态。例如,我们可以创建一个名为userReducer
的Reducer来处理用户数据:
const initialState = {
user: null,
loading: false,
error: null
};
const userReducer = (state = initialState, action) => {
switch (action.type) {
case 'FETCH_USER_PENDING':
return {
...state,
loading: true,
error: null
};
case 'FETCH_USER_FULFILLED':
return {
...state,
loading: false,
user: action.payload
};
case 'FETCH_USER_REJECTED':
return {
...state,
loading: false,
error: action.payload
};
default:
return state;
}
};
在上面的示例中,我们定义了一个userReducer
函数,它根据不同的Action类型更新用户状态。当FETCH_USER_PENDING
动作被分发时,我们将loading
状态设置为true
,并将error
状态设置为null
。当FETCH_USER_FULFILLED
动作被分发时,我们将loading
状态设置为false
,并将user
状态更新为Action的payload。当FETCH_USER_REJECTED
动作被分发时,我们将loading
状态设置为false
,并将error
状态更新为Action的payload。
在组件中使用Action。你可以在组件中使用connect
函数来连接Redux存储,并在组件中调用Action函数。当Action函数被调用时,Redux Promise中间件会自动处理Promise对象的状态,并分发相应的Action。例如:
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { fetchUser } from './actions';
const UserComponent = ({ user, fetchUser }) => {
useEffect(() => {
fetchUser();
}, [fetchUser]);
if (user.loading) {
return Loading...;
}
if (user.error) {
return Error: {user.error};
}
return (
User: {user.name}
Email: {user.email}
);
};
const mapStateToProps = state => {
return {
user: state.user
};
};
export default connect(mapStateToProps, { fetchUser })(UserComponent);
在上面的示例中,我们使用connect
函数将Redux存储中的user
状态映射为组件的属性。我们还将fetchUser
Action创建函数映射为组件的属性。在组件加载时,我们使用useEffect
钩子调用fetchUser
函数来发起异步操作。
这样,你就可以使用Redux Promise来简化处理异步操作的流程了。当调用Action函数时,Redux Promise中间件会自动处理Promise对象的状态,并根据Promise的状态分发相应的Action。