猿问

为什么我的自定义钩子被调用了这么多次?

我正在尝试实现一个自定义挂钩来为应用程序提供访客购物车。我的钩子环绕着useMutationApollo的钩子,它将购物车 ID 保存在 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!

我刚刚开始使用钩子,所以我仍然无法理解它们的工作方式。为什么有这么多的钩子调用?


谢谢您的回复!


牧羊人nacy
浏览 215回答 1
1回答

LEATH

将钩子视为直接在组件中具有相同的代码。这意味着每次组件渲染时,钩子都会运行。例如你定义: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如果未记忆接收函数的组件,则使用没有实际好处。
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答