问题描述
export const Filters: FC = observer(() => (
<div className={`filters ${viewmodel.isDragged ? 'filters--dragged' : ''} ${!viewmodel.isOpened ? 'filters--collapsed' : ''}`}
style={viewmodel.position}>
<FiltersHeader/>
<FiltersBody/>
</div>
));
这个组件用 observer
中的 mobx-react-lite
修饰。字段 position
用 @observable
包中的 mobx
装饰器装饰。 position
由字段 left: number
和 top: number
组成。
我想拖动这个组件。为了实现它,我在用户触发 position
时重新初始化 mousemove
。
问题在于 <FiltersHeader/>
和 <FiltersBody/>
不是小组件,渲染它们需要一段时间。每次我更改 viewmodel.position
React 时都会重新渲染整个树。不仅是FiltersHeader和FiltersBody,还有他们的孩子和他们的孩子等等。
为什么 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
。