Почему мой пользовательский хук вызывается так много раз? - PullRequest
3 голосов
/ 19 сентября 2019

Я пытаюсь реализовать пользовательский хук, чтобы предоставить приложению гостевую корзину.Мой хук обхватывает хук useMutation от Apollo и сохраняет идентификатор корзины в файле cookie, а также предоставляет функцию «сброса» корзины (в основном, для удаления файла cookie при размещении заказа).

Кодовое время!(некоторый код опущен для краткости):

export const useGuestCart = () => {
    let cartId;
    const [createCart, { data, error, loading }] = useMutation(MUTATION_CREATE_CART);
    console.log(`Hook!`);

    if (!cartId || cartId.length === 0) {
        createCart();
    }
    if (loading) {
        console.log(`Still loading`);
    }
    if (data) {
        console.log(`Got cart id ${data.createEmptyCart}`);
        cartId = data.createEmptyCart;
    }

    const resetGuestCart = useCallback(() => {
        // function body here
    });

    return [cartId, resetGuestCart];
};

В моем компоненте я просто получаю идентификатор корзины, используя let [cartId, resetCart] = useGuestCart();.

Когда я запускаю свой модульный тест (используя Apollo для обеспечения имитации мутации), я вижу, что перехваченный вызывается несколько раз, с выводом, который выглядит примерно так:

console.log src/utils/hooks.js:53
    Hook!

  console.log src/utils/hooks.js:53
    Hook!

  console.log src/utils/hooks.js:59
    Still loading

  console.log src/utils/hooks.js:53
    Hook!

  console.log src/utils/hooks.js:62
    Got cart id guest123

  console.log src/utils/hooks.js:53
    Hook!

  console.log src/utils/hooks.js:53
    Hook!

I 'Я только начинаю с крючками, поэтому мне все еще трудно понять, как они работают.Почему так много обращений к крючку?

Спасибо за ваши ответы!

1 Ответ

2 голосов
/ 19 сентября 2019

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

Например, вы определяете:

let cartId;
// ...
if (!cartId || cartId.length === 0) {
    createCart();
}

Содержимое внутри оператора будет выполняться при каждом рендеринге, так как cartId создается каждый развремя и не имеет никакого значения в этой точке.Вместо использования if операторов используйте useEffect:

export const useGuestCart = () => {
    const [cartId, setCartId] = useState(0);
    const [createCart, { data, error, loading }] = useMutation(
        MUTATION_CREATE_CART
    );
    const resetGuestCart = () => {
        // function body here
    };

    useEffect(() => {
        if(!cartId || cartId.length === 0){
            createCart();
        }
    }, [cartId]);

    useEffect(() => {
        // Here we need to consider the first render.
        if (loading) {
            console.log(`Started loading`);
        } else {
            console.log(`Finished loading`);
        }
    }, [loading]);

    useEffect(() => {
        // Here we need to consider the first render.
        console.log(`Got cart id ${data.createEmptyCart}`);
        setCartId(data.createEmptyCart);
    }, [data]);

    return [cartId, resetGuestCart];
};

Также обратите внимание, что использование useCallback не дает никакой реальной выгоды, если компонент, который получает функцию, не запоминается.

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