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-liteobserver。字段 position 使用 mobx 包中的 @observable 装饰器装饰。 position 由字段 left: numbertop: 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