Тестирование Custom Hook и использование эффекта не стрельбы - PullRequest
3 голосов
/ 18 июня 2019

Я тестирую небольшой пользовательский хук, и я не могу заставить useEffect внутри него сработать.У меня есть хук в смонтированном компоненте, и я успешно протестировал другие пользовательские хуки, которые не имеют useEffect с этим методом.Ссылка устанавливается на false, как и ожидалось (и прерывается, как ожидается, если установлена ​​на true), но никогда не обновляется до true, когда useEffect должен был работать.Код работает при запуске вне теста.

Мой хук:

export default function useIsComponentMounted() {
    const isMountedRef = useRef(false);
    useEffect(() => {
        isMountedRef.current = true;
        return function cleanup() {
            isMountedRef.current = false;
        };
    }, []);
    return isMountedRef.current;
}

Мой метод монтажа:

function TestHook(props) {
    const { callback } = props;
    callback();
    return <div />;
}

export const testHook = callback => mount(<TestHook callback={callback} />);

Мой тест:

describe('useIsComponentMounted', () => {
    it('should keep track of if a component is mounted', () => {
        let expected = true;
        let mounted;
        const component = testHook(() => {
            mounted = useIsComponentMounted();
        });
        expect(mounted).toBe(expected);
        component.unmount();
        expected = false;
        expect(mounted).toBe(expected);
    });
});

1 Ответ

2 голосов
/ 18 июня 2019

Вот что я думаю, что происходит:

useEffect происходит после рендеринга, поэтому, когда вы ожидаете, что mounted будет истинным, useEffect еще не запущен.Обновление ссылки не вызывает повторного рендеринга, поэтому ваш компонент никогда не обновляется.

Я получил это для работы путем принудительного обновления, вызывая component.setProps() перед каждым ожиданием:

    it('should keep track of if a component is mounted', () => {
        let mounted;
        const component = testHook(() => {
            mounted = useIsComponentMounted();
        });
        component.setProps(); // Feels a bit hacky, but it forces a re-render
        expect(mounted).toBe(true);
        component.unmount();
        component.setProps(); // This apparently even works after unmount!
        expect(mounted).toBe(false);
    });

Эта диаграмма полезна для отображения, когда происходят рендеринг, обновления DOM, useEffect, useLayoutEffect и рисование: https://raw.githubusercontent.com/donavon/hook-flow/master/hook-flow.png

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...