背景
得到需求要做一个电商平台SKU(商品)数据展示的app,sku有几个属性维度,比如所属仓库(fc),关心的数据日期区间(dateRange)等, 类似下图的设计
其中page 1,2,3点击后分别对应不同的数据块,可能是仓储水平,历史订单等各种业务数据
目标
如何优雅的设计state来实现这个需求,并且快速交付
可选方案
这个app中的仓库,商品,日期是全局的,会在各个组件中使用,针对这种情况,有两种可能的方法:
- 使用redux,把商品,日期,仓库放到container级别的state里,修改通过reducer,state修改后再通过props传达到各个子组件中
- 使用react hooks和function component
实现
方案1代码比较繁复,这个业务场景虽然看真实设计图好像很复杂,但是梳理之后是比较清晰的,并不是非用redux不可的场景,而且redux中异步读取数据还需要redux-saga等包的协同,开发效率不高。因此最终选择了方案2
最外层container中用react hooks声明全局state
const [fc, setFc] = useState('仓库');
const [sku, setSku] = useState('商品');
const [tab, setTab] = useState('数据块');
const [dates, setDates] = useState([moment().add(-7, 'days'), moment()]);
一个或多个参数选择组件,接收这些属性作为props,并且把hook的修改方法作为props修改的回调传入
<Select
showSearch
placeholder="Select FC"
defaultValue={props.fc}
optionFilterProp="children"
onChange={props.setFc} // 通过props传入的set方法设置上层组件的state
>
数据块组件接收这些属性作为props,读取数据
// container组件调用数据组件
<DataComponent
sku={sku}
fc={fc}
tab={tab}
changeFC={setFc}
changeSku={setSku}
changeTab={setTab}
></DataComponent>
//数据组件设计,主要是读取数据
const DataComponent = (props)=>{
useEffect(() => {
const fetchData = async (url, setFunc) => {
const result = await request(url);
setFunc(result);
};
fetchData(`url&{parameter}`, setMasterData);
}, [props.sku]);//监听全局变量的修改,改变时重新读取数据
}
总结
这样就可以很清晰的完成整个app的实现了,优点有:
- 代码清晰易于维护
- 对每个数据块组件,可以很好的控制数据读取和渲染,只有该数据块关心的数据发生变化时才刷新(通过useEffect的第二个参数控制)