1.在项目中下载工具包Redux、React-redux、Redux-saga
yarn add redux
yarn add react-redux
yarn add redux-saga
2.在src目录下创建Redux文件夹以及对应目录
3.在store.js里面引入createStore
创建store:调用createStore()方法得到store,方法中传入的参数为一个reducer,这个reducer应该从reducers目录下引入,直接引入合并后的index.js文件就可以,然后暴露store
import {createStore} from "Redux"
import bigReducer from "./reducers/index"
const store = createStore(bigReducer)
export default store
4.所以接下来在reducers目录下创建对应的reducer文件,并且创建一个合并所有reducer的index.js文件
5.在index.js文件中合并reducer,需要引入 combineReducers
工具
import { combineReducers } from "redux";
import usersReducer from "./usersReducer";
export default combineReducers({
usersRC:usersReducer
})
6.在对应的reducer中执行派发的action
export default function reducer(state={
user:[],
token:"",
userInfo:null
},action){
switch(action.type){
default:
return state
}
}
7.在src的index.js文件中引入store,然后引入Provider,并把store注入到i项目中
import store from "./redux/store"
import {Provider} from "react-redux"
ReactDOM.render(
<Provider store={store}><App /></Provider>,
document.getElementById('root')
);
8.在组件中引入{connect}
高阶组件,通过他将组件暴露出去,并且拿到仓库中的数据
import {connect} from "react-redux"
//...
class index extends componet{
//...
render(){
return(
//...
)
}
}
const mapStateToProps = (state)=>{
return {
token:state.usersRC.token,
userInfo:state.usersRC.userInfo
}
}
export default connect(mapStateToProps)(index)
9.当页面触发要修改数据的事件的时候,在该事件内部通过this.props.dispatch()来将对应的action派发给saga,在saga中匹配到相同的type属性后,会进入saga执行相应的代码(这的action应该写到actions文件夹下)
onFinish = async(values) => {
this.props.dispatch({
type:"loginSaga",
payload:values
})
// const res = await login(values);
// console.log(res);
// if(res.data.code){
// message.success("登录成功");
// setLocalStorage("token",res.data.data.token);
// setLocalStorage("userInfo",res.data.data.userInfo);
// this.props.history.push("/home");
// }else{
// message.error("登录失败");
// }
};
10.在saga中创建一个index,js文件,在该文件中写对应的异步请求,派发action
通过call方法发起异步请求,得到数据后,通过put方法派发对应的action给reducer,使用takeEvery来监听组件发来的action的type属性,type匹配后执行对应的生成器代码
import { call, put, takeEvery } from "redux-saga/effects"
//login请求
import { login } from "../../apis/users"
// 登录模块
function* asyncLogin({ payload }) {
//发起登录请求,并将结果返回
const res = yield call(login, payload)
//拿到结果
const { token, userInfo } = res.data.data
// 执行派发
yield put({ type: "initUser", payload: { token, userInfo } })
}
export default function* index() {
//监控action的type
yield takeEvery("loginSaga", asyncLogin)
}
put方法派发对应的action给reducer后,在对应的reducer里面匹配action的type属性,匹配成功执行对应的代码
export default function reducer(state={
user:[],
token:"",
userInfo:null
},action){
switch(action.type){
case "initUser":
return {
...state,
token:action.payload.token,
userInfo:action.payload.userInfo
}
default:
return state
}
}
11.返回到store文件中,引入applyMiddleware,以及saga中间件生成器sagaMiddleWareCreator,调用他得到中间件,将得到的中间件通过applyMiddleware,加入到创建store时reducer参数的后面。引入saga目录下的index,调用生成的中间件的run方法,把引入的index作为参数传入
import {createStore,applyMiddleware} from "redux"
import bigReducer from "./reducers"
import sagaMiddeleWareCreator from "redux-saga"
import saga from "./saga/index.js"
import {composeWithDevTools} from "redux-devtools-extension"
const sagaMiddeleWare = sagaMiddeleWareCreator()
// 创建store仓库
const store = createStore(bigReducer,composeWithDevTools(applyMiddleware(sagaMiddeleWare)))
sagaMiddeleWare.run(saga)
export default store
额外拓展-Redux浏览器插件
代码中加载插件
下面就可以正常的下载并安装这个插件。
如果要是在浏览器使用这个插件,那就需要我们在代码中安装一个插件
yarn add redux-devtools-extension
在代码中引入这个插件(store.js文件中)
// 引入工具插件
import { composeWithDevTools } from 'redux-devtools-extension';
const store = createStore(quantityReducer,composeWithDevTools());
调用createStore函数来创建store的时候,我们就可以引入工具插件
如果你代码中有到了中间件,代码写法为
// 引入工具插件
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from "redux-logger"
const store = createStore(quantityReducer,composeWithDevTools(applyMiddleWare(logger)));
效果如下: