简体   繁体   English

React-testing-library - 避免重新渲染子组件

[英]React-testing-library - avoid rerender of child component

I am trying to migrate a test from enzyme to React Testing Library我正在尝试将测试从酶迁移到反应测试库

It's goal in enzyme was "should not force re-render of child if child is unaffected"酶的目标是“如果孩子不受影响,不应该强制重新渲染孩子”

    const wasRendered = jest.fn();

    const Component = (props) => (
        <div {...props} />
    );

    const ChildComponent = () => {
        wasRendered();
        return <div>Hello</div>;
    };

    const SkinnableParent = Skinnable(config, Component); //Skinnable is a higher order component applied from our code. 
    const SkinnableChild = Skinnable(config, ChildComponent);

    const subject = mount(
        <SkinnableParent>
            <SkinnableChild />
        </SkinnableParent>
    );

    // Sending props to force parent to re-render
    subject.setProps({className: 'foo'});
    const expected = 1;
    const actual = wasRendered.mock.calls.length;

    expect(actual).toEqual(expected);

With testing library I am trying to use the rerender functionality.通过测试库,我正在尝试使用重新渲染功能。

    const wasRendered = jest.fn();
    
    const Component = (props) => {
        return <div {...props} />
    };

    const ChildComponent = () => {
        wasRendered();
        return <div>Hello</div>;
    };

    const SkinnableParent = Skinnable(config, Component); //Skinnable is a higher order component applied from our code. 
    const SkinnableChild = Skinnable(config, ChildComponent);

    const RootComponent = ({className}) => {
        return (
        <SkinnableParent className={className}>
            <SkinnableChild />
        </SkinnableParent>
        )
    };

    const {rerender} = render(<RootComponent />);

    rerender(<RootComponent className='foo' />);

    const expected = 1;
    const actual = wasRendered.mock.calls.length;

    expect(actual).toEqual(expected);

The problem is that the actual result is 2 with RTL.问题是 RTL 的实际结果是 2。 The Child Component is being rerendered as well.子组件也正在重新渲染。

Is there a way to achieve the same result as in the previous enzyme implementation?有没有办法达到与之前酶实施相同的结果?

There's nothing stopping the rerender of ChildComponent in that test.在该测试中没有什么可以阻止 ChildComponent 的重新呈现。 Your enzyme test is not testing what you thought it was.您的酶测试不是测试您认为的。 The only way to stop the rerender from the child component in this case would be to wrap it with React.memo在这种情况下,停止从子组件重新渲染的唯一方法是用 React.memo 包装它

When a parent component is rendered, all the child components will re-render, unless stopped by memo or a shouldComponentUpdate implementation returning false.渲染父组件时,所有子组件都将重新渲染,除非被 memo 或 shouldComponentUpdate 实现返回 false 停止。

React has good performance because even when a component is re-render, it may not need conciliation in the DOM (which is the heavy computational burden. See https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action React 具有良好的性能,因为即使重新渲染组件,它也可能不需要在 DOM 中进行调解(这是繁重的计算负担。请参阅https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in -行动

You should't worry about avoiding re-renders unless the JS in the component is expensive除非组件中的 JS 很昂贵,否则您不必担心避免重新渲染

See this sandbox, replicating your test case, and you'll see it renders twice https://codesandbox.io/s/romantic-river-hcos6查看这个沙箱,复制你的测试用例,你会看到它渲染了两次https://codesandbox.io/s/romantic-river-hcos6

in this case, using memo, it'll only render once https://codesandbox.io/s/condescending-lovelace-6z2j4在这种情况下,使用备忘录,它只会渲染一次https://codesandbox.io/s/condescending-lovelace-6z2j4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM