如何避免重新呈现子组件

时间:2020-01-02 13:58:04

标签: javascript reactjs

我在stackoverflow上发现了类似的问题,但没有一个使我解决。

我正在使用带有功能组件的react 16.12.0。 我有这个应用程序:

const App: React.FC<Props> = (props) => {
    const [value1, setValue1] = useState<number>(1);
    const [value2, setValue2] = useState<boolean>(true);

    function incrementValue1(){
        setValue1(value1+1);
    }

    function sendToServer(){
        ...do something...
    }

    return (
        <>
            <Row>
                <Col>
                    <Child value2={value2} sendToServer={sendToServer} />
                </Col>
            </Row>
            <Row>
                <Col>
                    <Button variant="outlined"
                            color="primary"
                            size="large"
                            onClick={incrementValue1}>
                        Increment value1
                    </Button>
                </Col>
            </Row>
        </>
    );
};

export default App;

尽管父级正在更改一个值,这与子级组件无关,但是每次父级组件渲染时,子级组件都会重新渲染。

我了解了备忘录,可以将任何组件合并到备忘录中,并使用备忘录的第二个参数告诉何时渲染。但我不确定是否正确。在重写很多类之前,我想知道哪种方法是正确的。 例如:

const Child: React.FC<Props> = React.memo(props) => {
    ...Logic from child component...
},[props.value2])

正确的做法是什么?

3 个答案:

答案 0 :(得分:1)

这里是React Memo documentation

如果您的功能组件使用相同的道具呈现相同的结果,则可以将其包装在对React.memo的调用中,以在某些情况下通过记忆结果来提高性能

因此,基本上,如果将Child组件包装到React.memo中,则在道具不随时间变化的情况下,该组件将不会重新渲染

// Child component
function Child({value2, sendToServer}) {
  ...
}

export default React.memo(Child);

如果您只想在属性Child发生变化时重新渲染value2组件,仅 ,则可以使用第二个参数,该参数应返回true不需要重新呈现组件时

它将是:

export default React.memo(
  Child, 
  (prevProps, nextProps) => prevProps.value2 === nextProps.value2
);

答案 1 :(得分:1)

您可以只使用普通的React.memo

const Child = React.memo((props) => {
...
});

这样,如果孩子的所有道具都相等,孩子将跳过重新渲染。

您需要做的另一项更改是将sendToServerReact.useCallback包裹

const sendToServer = React.useCallback(function() {
...
}, []);

useCallback将对sendToServer的引用与整个渲染器相同,因此该Child的记忆将起作用。这就是useCallback存在的确切用例。

答案 2 :(得分:1)

您应该理解,用memo包装所有组件也将花费一些资源。因此,我建议您不要在乎重新渲染组件,只要这个重新渲染不会影响任何“昂贵”的计算,这不是一个大问题。

对于那些(昂贵的)代码部分,我建议您使用useMemo。因此,仅在实际需要的地方使用该优化。