【问题标题】:How to mock useRef hook with react-native using enzyme如何使用酶模拟 useRef 钩子和 react-native
【发布时间】:2021-04-02 20:56:34
【问题描述】:

我想为我的 React-native 应用程序编写测试。我的父组件将执行子组件中的方法。 我的子组件正在使用 Hooks forwardRef、useImperativeHandle、Ref 如下所示

childs.tsx

export interface RefChild {
    toggle: () => void,
    close: () => void
}

const Child = forwardRef((props: ChildProps, ref: Ref<RefChild>) => {
    const [isVisible, setIsVisible] = useState(false);
    useImperativeHandle(ref, () => ({ toggle, close }));

    const toggle = () => {
        setIsVisible(!isVisible);
    }

    const close = () => {
        setIsVisible(false)
    }

    return (...mycomponent)
}

我的父组件正在使用 'ref' 调用

ref={(el: RefChild) => childRef.current = el}

这允许我从父级中调用“切换”和“关闭”方法。 现在,我不明白如何在我的测试中做同样的事情

我的父母-test.tsx:

describe('Parent', () => {
    let wrapper: ShallowWrapper;
    let props: any;
    beforeEach(() => {
        props = createTestProps({});
        wrapper = shallow(<Parent {...props} />);
    });

//this is what I am currently trying to do, but not working
//test 1 (not working)
    it("useRef child", () => {
        const useRefSpy = jest.spyOn(React, 'useRef').mockReturnValueOnce({ current: <Child/> });
        expect(useRefSpy).toBeCalled();
        useRefSpy.current.toggle();
    })

//test 2 (not working)
    it("useRef child2", () => {
        const ref = {
            current: {
                toggle: jest.fn(),
                close: jest.fn()
            }
        }

        ref.current.toggle();
    })

//test 3 (not working)
    it("useRef child3", () => {
        wrapper.instance().childref.current.toggle(); //failing as functional components don't have instance
    })
})

我的 React 和 RN 版本是:

    "react": "16.13.1",
    "react-native": "0.63.3"

谁能解释我应该如何做到这一点?

【问题讨论】:

    标签: react-native jestjs hook enzyme use-ref


    【解决方案1】:

    正如您在问题中提到的,functional 组件中没有instance,我认为有更好的方法来处理来自parent componentclose 函数,每个函数都使用布尔值prop他们和听这个值的变化是这样的:

    您在父组件中有一个名为 isClose 的状态设置为 false,然后在子组件中您使用如下内容:

    useEffect(() => {
       if(isClose){
         //call close function
         close()
       }
    }, [isClose])
    

    但顺便说一下,在您当前的设置中,我认为您需要像这样模拟 useRef 钩子:

    
    const useRefSpy = jest
      .spyOn(React, "useRef")
      .mockReturnValueOnce(() => ({ current: <Child /> }));
    

    【讨论】:

    • 感谢您的回复。我明白你所说的使用 useEffect 是什么意思。如果我像 &lt;Child isClosed={isClosed}/&gt; 这样渲染孩子,我怎样才能让 useEffect 运行?
    • 你在Child 组件中使用我上面提到的useEffect 并将isClosed 属性传递给Child,就像你提到的那样,每当你想运行effect 时,只需传递一个isClosed 的真正标志是这样的:&lt;Child isClosed={true}/&gt;
    • 嗨,抱歉耽搁了,圣诞节比计划花费了我更多的时间 :)。最终,这是有效的,它也消除了我孩子的参考的需要。但是,当我从父级更改值 isClosed (以修改子级)时,它会重新渲染我的父级,因为状态处于父级中。我使用 ref 只能更改 Child 状态,以便我的 Child 只会重新渲染。你有什么建议吗?
    • 圣诞快乐。所以我认为你必须去嘲笑useRef,正如我在useRefSpy 示例中向你展示的那样
    • 嗨,我无法以这种方式调用切换和关闭 fct。我正在做useRefSpy.current.toggle(),但它只是失败了
    猜你喜欢
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 2020-05-09
    • 1970-01-01
    • 2020-04-08
    • 2021-04-20
    • 2022-01-08
    • 1970-01-01
    相关资源
    最近更新 更多