最近 Code Review 代码,发现几个项目中可能遇到的问题,可以进行的优化。
以下部分借鉴同事的总结(PS:问题代码是我的例子)
先从一个需求说起,某个页面中有个 Switch 开关,开关的状态是从后端接口获取的并保存在 Redux 中,如果点击这个开关,需要切换其状态并向后端发送一个请求。
现有逻辑为:
页面初始化时从后端接口获取状态并保存在 Redux 中(假设为 checked 字段),然后通过 props 将传到 Switch 组件所在的页面
该页面接收到 props 时,将 checked 这个 props 保存在页面的 state 中,然后 Switch 组件使用页面的 state 中的值
点击 Switch 开关时修改页面 state 中的 checked 值,然后再触发 Redux 中的一个 action (已使用 redux-thunk 处理异步逻辑)去请求后端接口
这样就会出现一个问题,如果接口请求失败,但是页面显示的开关状态已经切换,导致 UI 显示与实际状态不一致,并且如果其他页面用到这个状态,可能会导致一些意料之外的问题。
错误代码示范:
<Switch
onChange={(checked)=> (
this.setState({ salesStatus = !checked}),
this.switchSales )}
checked={salesStatus}
style={{ marginLeft: 16 }}
disabled={!quickpay.edit}
/>
正确的操作应该为:
<Switch
onChange={this.switchSales}
checked={salesStatus}
loading={XXXXX}
style={{ marginLeft: 16 }}
disabled={!quickpay.edit}
/>
页面初始化时从后端接口获取状态并保存在 Redux 中(假设为 checked),并将状态通过 props 传递到 Switch 开关组件中,中间不做任何处理
点击 Switch 开关时,给其一个 loading 状态,同时触发 Redux 中的一个 action 去请求后端接口,请求完成后根据请求结果决定是否修改 Redux 中的 checked 值,并取消 loading 状态
一个很简单的需求涉及到两个 React 架构中的理念:单一数据源和单项数据流。
单一数据源
单一数据源即任何一个状态只保存一份,例如上述需求中的 checked 状态仅保存在 Redux 中即可,不要在某个页面或组件中重新保存一份这个状态值。
注意,根据需求偶尔也会有特殊情况,例如 Ant Design Form 中通过 getFieldDecorator 包装的组件可能需要对传入 value 进行处理后再使用。
单向数据流
React 中的数据流均为单向的,父组件通过 props 向子组件传递数据,props 发生改变后,组件会自动重新渲染。并且一个组件不能修改他的 props 值。
如上述需求中的 checked 状态,通过 props 从顶层一层一层向下传递,而要修改他的时候,必须显式地触发一个 action 去修改他。
网友评论