React 重新渲染组件的完整树
React rerender full tree of the component
我有一个组件:
export const Filters: FC = observer(() => (
<div className={`filters ${viewModel.isDragged ? 'filters--dragged' : ''} ${!viewModel.isOpened ? 'filters--collapsed' : ''}`}
style={viewModel.position}>
<FiltersHeader/>
<FiltersBody/>
</div>
));
此组件装饰有来自 mobx-react-lite
的 observer
。字段 position
使用 mobx
包中的 @observable
装饰器装饰。 position
由字段 left: number
和 top: number
.
组成
我想拖动这个组件。为了实现它,我在用户触发 mousemove
.
时重新初始化 position
问题是 <FiltersHeader/>
和 <FiltersBody/>
不是小组件,渲染它们需要一段时间。每次我更改 viewModel.position
React 都会重新渲染整个树。不仅是 FiltersHeader 和 FiltersBody,还有它们的 children 和它们的 children,等等
为什么 React 会那样做?我的意思是,FiltersHeader 没有属性。如果组件的属性没有改变,React 不应该再次重新渲染组件。还是应该?
此代码同样有效
export const Filters: FC = () => {
const [position, setPosition] = useState(viewModel.position);
useEffect(() => {
reaction(() => viewModel.position, value => setPosition(value));
}, []);
return (
<div className={`filters ${viewModel.isDragged ? 'filters--dragged' : ''} ${!viewModel.isOpened ? 'filters--collapsed' : ''}`}
style={position}>
<FiltersHeader/>
<FiltersBody/>
</div>
);
}
正如其他评论者所说,默认情况下 React 不应用优化,因此每个子组件都会在父组件重新渲染时重新渲染(即使它没有道具)。
您可以将它们包裹在 React.memo
中,或者实际上也包裹在 observer
中,因为它也会自动应用 memo
。
我有一个组件:
export const Filters: FC = observer(() => (
<div className={`filters ${viewModel.isDragged ? 'filters--dragged' : ''} ${!viewModel.isOpened ? 'filters--collapsed' : ''}`}
style={viewModel.position}>
<FiltersHeader/>
<FiltersBody/>
</div>
));
此组件装饰有来自 mobx-react-lite
的 observer
。字段 position
使用 mobx
包中的 @observable
装饰器装饰。 position
由字段 left: number
和 top: number
.
我想拖动这个组件。为了实现它,我在用户触发 mousemove
.
position
问题是 <FiltersHeader/>
和 <FiltersBody/>
不是小组件,渲染它们需要一段时间。每次我更改 viewModel.position
React 都会重新渲染整个树。不仅是 FiltersHeader 和 FiltersBody,还有它们的 children 和它们的 children,等等
为什么 React 会那样做?我的意思是,FiltersHeader 没有属性。如果组件的属性没有改变,React 不应该再次重新渲染组件。还是应该?
此代码同样有效
export const Filters: FC = () => {
const [position, setPosition] = useState(viewModel.position);
useEffect(() => {
reaction(() => viewModel.position, value => setPosition(value));
}, []);
return (
<div className={`filters ${viewModel.isDragged ? 'filters--dragged' : ''} ${!viewModel.isOpened ? 'filters--collapsed' : ''}`}
style={position}>
<FiltersHeader/>
<FiltersBody/>
</div>
);
}
正如其他评论者所说,默认情况下 React 不应用优化,因此每个子组件都会在父组件重新渲染时重新渲染(即使它没有道具)。
您可以将它们包裹在 React.memo
中,或者实际上也包裹在 observer
中,因为它也会自动应用 memo
。