深入理解redux
深入Redux
简述
在快速理解redux中,我简单的介绍了redux的基础内容,本篇文章中,我们将再度深入redux。
redux解决的问题
- 数据和函数的层层传递
- 多个组件同时修改某全局变量
一、react数据流
- 众所周知,react的单向数据流是这样的,父组件可以向子组件传递数据
我们通常用过状态提升将数据存于高阶函数中,使我们的子组件尽可能的更"纯",更好的实现代码复用。 - 可能在页面结构简单的小型项目中我们还没觉得有什么不妥,但是倘若在页面结构稍复杂的项目中,就会变成这样
D组件中的数据存于Container中,要通过Container -> Content -> B -> D
才能到达D组件。
当然,这对我们聪明有能干的开发者们并不算什么,耗些时间也能刚出来。 - Then,这种页面,你还能搞得定吗?
就算你能搞定,你的代码中也有大量的冗余,从Container到N之间的所有组件都要传递N需要的props - 所以,为了解决层层传递,react-redux就出现了
它利用了react中的context,在Container的context里创建store,使Container的所有子组件,孙组件等等都可以直接获取store中的内容。
二、修改store
我曾在快速理解redux中提起,为了解决模块(组件)之间需要共享数据 和 数据可能被任意修改导致不可预料的结果 的矛盾,redux团队创建了dispatch
。So 不可预料的结果究竟是什么?
我们思考一个问题,假如所有的组件都以 store.xxx = xxx; // 伪代码
这种方式修改全局变量,会引发什么问题?
我们再思考,为何python等语言会存在线程锁,数据库也存在锁,操作系统的生产者/消费者问题等等
假如A和B同时修改store,store是遵从A还是遵从B?
为了避免以上情况引发死锁redux想出了一个办法:封装一个dispatch函数,接收一个action对象作为参数,每当组件想要修改store时必须给dispatch传递action,然后再store内部根据action对象的type将dispatch分发到相应的队列中,每一时刻仅执行一个dispatch
三、redux异步问题
思考这样一个情景,我们从后端的接口获取了数据,我们想将其存入store中。但是当执行到reducer时,数据是否已经获取到?假如没有,又该怎么办?
就在此时,中间件出现了,例如 redux-saga, redux-thunk 等等。
redux-saga 使用了generate生成器,使开发者可以按同步思路的书写异步代码,再根据action的type选择相应reducer更新store
function *fetchNodeDetailByNodeId({ payload: { nodeId } }, { call, put }) { try { const { data, status }= yield call(fetchNodeDetailByNodeId, nodeId) if (data && status.errmsg === 'success') { yield put({ type: 'setStates', payload: { nodeDetailData: data, }, }); } else { message.info('开了个小差,再试一次吧..'); } } catch (error) { console.log(error); } },