为了防止将回调传递给我正在使用的子组件useReducer
反而。这避免了子组件在每个父渲染上重新渲染的问题,但缺点似乎是父组件和子组件之间的紧密耦合。通过紧密耦合,我的意思是子级需要明确了解父级定义的减速器所期望的操作的形状。
例如,想象一个日期选择器组件。在某些时候,该组件需要将新的日期/时间值传递给调用组件,以便可以保存(或以某种方式使用)数据。通过回调,我们可以有一个简单的 prop,比如saveDate={onSaveDate}
。日期选择器通过说“我期望这些道具”来定义合同。具体来说,我期望saveDate
带有签名的道具newDate => {}
。这个流程对我来说很有意义。
With useReducer
,父级通过dispatch
到日期选择器,并且日期选择器需要知道如何创建与减速器期望相匹配的操作。这可以通过在某个模块中定义动作创建者并将它们导入日期选择器来解决,但这对我来说感觉是倒退的。如果从应用程序中的各个组件调用日期选择器,则所有组件都需要就该接口(操作的形状)达成一致。这似乎不仅将一个组件与日期选择器耦合,而且将所有使用日期选择器的组件耦合在一起。
那么,我忽略了什么以及有哪些策略可以解决这个问题?不管怎样,我重新开始使用回调,其中更干净的代码比重新渲染的性能问题更有意义。
我建议使用父组件中的操作类型来柯里化调度,如下所示:
const Parent = () => {
const [state, dispatch] = useReducer(datepickerReducer, initialState)
// might wanna useCallback here if your DatePicker is pure
const changeDate = newDate => dispatch({ type: 'CHANGE_DATE', newDate })
return <DatePicker onChange={changedate} value={state} />
}
这样你的组件就与其他组件保持隔离,你可以像在钩子之前一样使用它。不过,如果您经常使用 datepickerReducer,每次都重新定义changeDate 会很烦人,所以我会使用一个自定义钩子来完成它:
const useDatepicker = init => {
const [date, dispatch] = useReducer(datepickerReducer)
const changeDate = useCallback(newDate => dispatch({ type: 'CHANGE_DATE', newDate }), [])
// I prefer using an object, makes it more convenient to reach values that would have been at the end of the array
return { date, changeDate, /* You could have resetDate here aswell */ }
}
// USAGE
const { date, changeDate } = useDatepicker(new Date())
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)