我的应用程序中有一些组件需要遵循全局控制的动态布局。这意味着,如果我的应用程序中的某些内容(例如,它是响应上下文或用户主题)发生更改,则每个组件都需要使用新的布局进行重新渲染。布局如下:
A | B | C C C C | D
为了封装来自客户端组件的样式和逻辑,我创建了Template
组件,该组件从MobX存储观察ResponsiveContext并在更改时重新呈现。因此,每个需要遵循布局的组件实际上都会渲染Template
并通过prop将React元素传递给它。但是可能有很多C
或只有1个,所以我没有手动传递C而是传递数据,而是回调以呈现它,而Template
使用回调准备和映射数据。从客户端的角度来看,是这样的:
function Client() {
return <Template
a={<div>A</div>}
b={<div>B</div>}
d={<div>D</div>}
cData={[1, 2, 3, 4]}
cRenderFunction={el => <div key={el}>{el}</div>}
/>
}
和模板组件如下所示:
function Template(props) {
const size = useUiStore().responsiveContext.size;
return <div>
<div>{props.a}</div>
<div>{props.b}</div>
<div>{prepareData(size, props.cData).map(props.cRenderFunction)}</div>
<div>{props.d}</div>
</div>
}
问题是.map(props.cRenderFunction)
仅创建React元素而不是React节点,因此客户端观察到的所有内容也被observer(Template)
观察到,从而产生了另一次重新渲染:observer(ClientComponent)
读取了可观察到的{{1 }}本身,然后在函数x
中进行渲染,该函数随后在渲染cRenderFunction
时被调用-因此2个组件观察到Template
(x
和Template
)。现在每次ClientComponent
突变x
重新渲染,然后Template
突变,然后再次重新渲染ClientComponent
。
我看到两种解决方案:
Template
)。以前我会使用来自mobx-react的ResponsiveContext
钩子,但现在已弃用它,我不知道如何替换它。代码如下:useObserver
function Template(props) {
const uiStore = useUiStore();
const size = useObserver(() => uiStore.responsiveContext.size);
// the same as before
}
观察到它。第二个选项对我来说似乎是一种解决方法,我认为这违反了性能,因为我需要创建成千上万个定期定期更新的元素。
哪个选项是最好的?如果是第一个,该如何替换不推荐使用的Template
API?如果是第二个,如何创建新的React节点并从客户端而不是useObserver
组件设置密钥?因为我看到的唯一方法是将另一个函数传递给Template
,该函数将基于数据生成密钥。