I'm trying to create a custom hooks in order to store Cart data.
The cart object:
{ uid: quantity, uid2: quantity2, ...}
The Hook I did:
import { useState } from "react";
// Return a new object without empty values
const clean = (obj) =>
Object.keys(obj).reduce((acc, key) => {
if (obj[key]) {
acc[key] = obj[key];
}
return acc;
}, {});
export const useCart = () => {
// Cart is [uid]=quantity
const [cart, setCart] = useState({});
const updateCart = ({ uid = 0, quantity = 1 }) => {
const newCart = clean({
...cart,
[uid]: quantity > 0 ? quantity : null
});
setCart(newCart);
console.log(" New Cart : ", JSON.stringify(newCart));
};
// Do are they reactive ? Or do we need to useState them
const count = Object.values(cart).reduce((acc, value) => acc value, 0);
// Return all
return { cart, updateCart, setCart, count };
};
The issue I have
The cart works fine for a single Item but when I update the DOM and re-ask for cart data, they're it's back to initial value.
I'm pretty sure it's because the updateCart()
is initialized with initial value who isn't updated... but I don't know how to do it ?
I also tried to use directly setCart()
on components instead of updateCart()
but nothing better.
I did an example to test it without my project: https://codesandbox.io/s/reverent-tess-8pymji
Thanks.
CodePudding user response:
The problem is that every time the route changes, it will reinitialise your React hook and that will also reinitialise the state on that hook.
You probably are looking to create your custom hook as a Singleton so that it could share the state across multiple components on different routes.
react-singleton-hook
is a really neat library that you can use in order to do just that.
You'll have to update the implementation of your hook a bit:
import { useState } from "react";
import { singletonHook } from "react-singleton-hook";
// Return a new object without empty keys
const clean = (obj) =>
Object.keys(obj).reduce((acc, key) => {
if (obj[key]) {
acc[key] = obj[key];
}
return acc;
}, {});
export const useCartImpl = () => {
// Cart is [uid]=quantity
const [cart, setCart] = useState({});
const updateCart = ({ uid = 0, quantity = 1 }) => {
const newCart = clean({
...cart,
[uid]: quantity > 0 ? quantity : null
});
setCart(newCart);
console.log(" New Cart : ", JSON.stringify(newCart));
};
// Do are they reactive ? Or do we need to useState them
const count = Object.values(cart).reduce((acc, value) => acc value, 0);
// Return all
return { cart, updateCart, setCart, count };
};
export const useCart = singletonHook({}, useCartImpl);
Here's an Update CodeSandbox for your ref.