文章目录
Redux的三大原则
◼ 单一数据源
整个应用程序的state被存储在一颗object tree中,并且这个object tree只存储在一个 store 中:
Redux并没有强制让我们不能创建多个Store,但是那样做并不利于数据的维护;
单一的数据源可以让整个应用程序的state变得方便维护、追踪、修改;
◼ State是只读的
唯一修改State的方法一定是触发action,不要试图在其他地方通过任何的方式来修改State:
这样就确保了View或网络请求都不能直接修改state,它们只能通过action来描述自己想要如何修改state;
这样可以保证所有的修改都被集中化处理,并且按照严格的顺序来执行,所以不需要担心race condition(竟态)的问题;
◼ 使用纯函数来执行修改
通过reducer将 旧state和 actions联系在一起,并且返回一个新的State:
随着应用程序的复杂度增加,我们可以将reducer拆分成多个小的reducers,分别操作不同state tree的一部分;
但是所有的reducer都应该是纯函数,不能产生任何的副作用;
Redux官方图
react-redux使用
◼ 安装react-redux:
yarn add react-redux
1、创建store管理全局状态
-src
—store
------- constants.js
先创建要使用的type常量
exportconstADD_NUMBER="add_number"exportconstSUB_NUMBER="sub_number"exportconstCHANGE_BANNERS="change_banners"exportconstCHANGE_RECOMMENDS="change_recommends"
-src
—store
------- reducer.js
再创建reducer管理状态
import*as actionTypes from"./constants"const initialState ={counter:100,banners:[],recommends:[]}functionreducer(state = initialState, action){switch(action.type){case actionTypes.ADD_NUMBER:return{...state,counter: state.counter + action.num }case actionTypes.SUB_NUMBER:return{...state,counter: state.counter - action.num }case actionTypes.CHANGE_BANNERS:return{...state,banners: action.banners }case actionTypes.CHANGE_RECOMMENDS:return{...state,recommends: action.recommends }default:return state
}}exportdefault reducer
-src
—store
------- index.js
在index导出整个store
import{ createStore }from"redux"import reducer from"./reducer"const store =createStore(reducer)exportdefault store
-src
—store
------- actionCreators.js
创建actionCreators,放修改状态的函数
import*as actionTypes from"./constants"import axios from"axios"exportconstaddNumberAction=(num)=>({type: actionTypes.ADD_NUMBER,
num
})exportconstsubNumberAction=(num)=>({type: actionTypes.SUB_NUMBER,
num
})exportconstchangeBannersAction=(banners)=>({type: actionTypes.CHANGE_BANNERS,
banners
})exportconstchangeRecommendsAction=(recommends)=>({type: actionTypes.CHANGE_RECOMMENDS,
recommends
})exportconstfetchHomeMultidataAction=()=>{// 如果是一个普通的action, 那么我们这里需要返回action对象// 问题: 对象中是不能直接拿到从服务器请求的异步数据的// return {}returnfunction(dispatch, getState){// 异步操作: 网络请求// console.log("foo function execution-----", getState().counter)
axios.get("http://123.207.32.32:8000/home/multidata").then(res=>{const banners = res.data.data.banner.list
const recommends = res.data.data.recommend.list
// dispatch({ type: actionTypes.CHANGE_BANNERS, banners })// dispatch({ type: actionTypes.CHANGE_RECOMMENDS, recommends })dispatch(changeBannersAction(banners))dispatch(changeRecommendsAction(recommends))})}// 如果返回的是一个函数, 那么redux是不支持的// return foo}
2、在项目index.js根节点引用
-src
— index.js
3、 在需要使用redux的页面或者组件中,通过connect高阶组件映射到该组件的props中
解耦store和class组件的耦合
redux中异步操作
◼ redux也引入了中间件(Middleware)的概念:
这个中间件的目的是在dispatch的action和最终达到的reducer之间,扩展一些自己的代码;
比如日志记录、调用异步接口、添加代码调试功能等等;
◼ 我们现在要做的事情就是发送异步的网络请求,所以我们可以添加对应的中间件:
这里官网推荐的、包括演示的网络请求的中间件是使用 redux-thunk
◼ redux-thunk是如何做到让我们可以发送异步的请求呢?
我们知道,默认情况下的dispatch(action),action需要是一个JavaScript的对象;
redux-thunk可以让dispatch(action函数),action可以是一个函数;
该函数会被调用,并且会传给这个函数一个dispatch函数和getState函数;
✓ dispatch函数用于我们之后再次派发action;
✓ getState函数考虑到我们之后的一些操作需要依赖原来的状态,用于让我们可以获取之前的一些状态;
如何使用redux-thunk
◼ 1.安装redux-thunk
如何使用redux-thunk
yarn add redux-thunk
◼ 2.在创建store时传入应用了middleware的enhance函数
通过applyMiddleware来结合多个Middleware, 返回一个enhancer;
将enhancer作为第二个参数传入到createStore中;
// 通过applyMiddleware来结合多个Middleware, 返回一个enhancerconst enhancer =applyMiddleware(thunkMiddleware);// 将enhancer作为第二个参数传入到createStore中const store =createStore(reducer, enhancer);
◼ 3.定义返回一个函数的action:
注意:这里不是返回一个对象了,而是一个函数;
该函数在dispatch之后会被执行;
constgetHomeMultidataAction=()=>{return(dispatch)=>{
axios.get("http://123.207.32.32:8000/home/multidata").then(res=>{const data = res.data.data;dispatch(changeBannersAction(data.banner.list));dispatch(changeRecommendsAction(data.recommend.list));})}}
combineReducers函数
◼ 事实上,redux给我们提供了一个combineReducers函数可以方便的让我们对多个reducer进行合并:
◼ 那么combineReducers是如何实现的呢?
事实上,它也是将我们传入的reducers合并到一个对象中,最终返回一个combination的函数(相当于我们之前的reducer函
数了);
在执行combination函数的过程中,它会通过判断前后返回的数据是否相同来决定返回之前的state还是新的state;
新的state会触发订阅者发生对应的刷新,而旧的state可以有效的组织订阅者发生刷新;
版权归原作者 顽皮宝 所有, 如有侵权,请联系我们删除。