为什么我的自定义钩子被调用了这么多次?
Why is my custom hook called so many times?
我正在尝试实现一个自定义挂钩来为应用程序提供访客购物车。我的钩子环绕着 Apollo 的 useMutation
钩子,它将购物车 ID 保存在 cookie 中,同时还为 "reset" 购物车提供了一个功能(基本上是在下订单时删除 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();
获取购物车的 ID。
当我 运行 我的单元测试(使用 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!
我只是开始使用钩子,所以我仍然无法理解它们的工作方式。为什么要调用这么多钩子?
感谢您的回复!
将钩子视为直接在组件中具有相同的代码。这意味着每次组件呈现挂钩时都会 运行.
比如你定义:
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
没有任何实际好处。
我正在尝试实现一个自定义挂钩来为应用程序提供访客购物车。我的钩子环绕着 Apollo 的 useMutation
钩子,它将购物车 ID 保存在 cookie 中,同时还为 "reset" 购物车提供了一个功能(基本上是在下订单时删除 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();
获取购物车的 ID。
当我 运行 我的单元测试(使用 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!
我只是开始使用钩子,所以我仍然无法理解它们的工作方式。为什么要调用这么多钩子?
感谢您的回复!
将钩子视为直接在组件中具有相同的代码。这意味着每次组件呈现挂钩时都会 运行.
比如你定义:
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
没有任何实际好处。