What would you use for a global state management? - Initalization from API needed

Hello, So long story short, I would like to have a global state management for my advertisements and want to display in multiple components(maybe even in the sidebar). This ads can have dynamic styling(like row-span-2, col-span-2 in a grid case). The initial advertisements should come from server so the initialization need to be a fetch call (or something else). What do you guys would recommand? My approach with Zustand failed(I'm still trying). This state should have a nextAdId too, which represents which ad should be rendered next. Thanks demo-repo(the code quality is bad): https://github.com/DZsolt01/nextjs-zustand-demo
GitHub
GitHub - DZsolt01/nextjs-zustand-demo: Zustand Demo
Zustand Demo. Contribute to DZsolt01/nextjs-zustand-demo development by creating an account on GitHub.
Solution:
I think this logic would ideally not be in a frontend at all. Basically you'd have endpoints like getSidebarAds, getSliderAds, and for the grid that's dynamic, it'd be something like getContent which would return an array of objects with type: "item" | "ad". You could then use this array to render either BusinessCard or Advertisement. And if you can handle it on BE, you can just look at all the available ads, and ensure these endpoints don't return duplicates....
Jump to solution
37 Replies
Juraj98
Juraj98•4mo ago
This looks like something react-query would be ideal for. You'd just have to write the fetch function so it returns correct data for rendering and handle the nextAdId somewhere (could be useState, context, whatever). But zustand should be usable too. What issue did you ran into with the current implementation?
Adek
Adek•4mo ago
The main problem which remained after trying a lot is not getting the good advertisment. Every time get only the advertisements[0] on stlyes
Adek
Adek•4mo ago
No description
Adek
Adek•4mo ago
The second advertisment should look different
Adek
Adek•4mo ago
GitHub
GitHub - DZsolt01/nextjs-zustand-demo: Zustand Demo
Zustand Demo. Contribute to DZsolt01/nextjs-zustand-demo development by creating an account on GitHub.
Juraj98
Juraj98•4mo ago
I'm unable to run the code, because ui/card is not commited. But if you're having issues with styling, I seems like you're trying to generate tailwind classes dynamically. This won't work, as tailwind generates CSS based on what's already included. (Docs) You should try using style prop for your dynamic styles.
Adek
Adek•4mo ago
I added the classes in tailwind config (safeList) so the classes are added, and the classNames works fine I hope now it's good
Adek
Adek•4mo ago
The classes are applied to the className, the problem is when I add a new Advertisment in BusinessCardWrapper.tsx the advertisment passed to it is always advertisments[0]
No description
Juraj98
Juraj98•4mo ago
I'm still confused by what are you trying to achieve. Because right now, you're rendering the same advertisement twice. But something tells me you want to render first ad before business card 3 and second in front of business card 7. Also, the current code increases the nextAdvertisement until it's 2, which makes it not render any ad. I think this could solve your problem?
const BusinessCardWrapper = ({
businessCards,
}: {
businessCards: BusinessCardProps[];
}) => {
const advertisements = useAdvertisementStore((state) => state.advertisements);
const advertisementIndexes = useMemo(() => {
return [3, 7];
}, []);

let currentAdIndex = 0;

return (
<>
<div className="grid auto-rows-[150px] grid-cols-5 gap-4 p-4">
{businessCards.map((card, mIndex) => {
let ad: ReactNode = null;

if (advertisementIndexes.includes(mIndex)) {
ad = (
<Advertisement
key={`adv-${mIndex}`}
advertisement={advertisements[currentAdIndex]}
/>
);
currentAdIndex++;
}

return (
<React.Fragment key={mIndex}>
{ad}
<div
key={`card-${mIndex}`}
className={`flex rounded-lg bg-neutral-500`}
>
{card.title}
</div>
</React.Fragment>
);
})}
</div>
</>
);
};
const BusinessCardWrapper = ({
businessCards,
}: {
businessCards: BusinessCardProps[];
}) => {
const advertisements = useAdvertisementStore((state) => state.advertisements);
const advertisementIndexes = useMemo(() => {
return [3, 7];
}, []);

let currentAdIndex = 0;

return (
<>
<div className="grid auto-rows-[150px] grid-cols-5 gap-4 p-4">
{businessCards.map((card, mIndex) => {
let ad: ReactNode = null;

if (advertisementIndexes.includes(mIndex)) {
ad = (
<Advertisement
key={`adv-${mIndex}`}
advertisement={advertisements[currentAdIndex]}
/>
);
currentAdIndex++;
}

return (
<React.Fragment key={mIndex}>
{ad}
<div
key={`card-${mIndex}`}
className={`flex rounded-lg bg-neutral-500`}
>
{card.title}
</div>
</React.Fragment>
);
})}
</div>
</>
);
};
Adek
Adek•4mo ago
The end result should be this:
No description
Adek
Adek•4mo ago
So there should be 2 blocks(ads) which are different from the cards Sorry for my bad english 😦 The basic idea would be to get all the ads from server, store it, and when I want to render an ad anywhere in the application I can do that, but the ad should be the next one in the list so I don't render the same ad
Juraj98
Juraj98•4mo ago
That how it looks for me..
No description
Adek
Adek•4mo ago
Sorry, I just got back to PC
Juraj98
Juraj98•4mo ago
(With the new code)
Adek
Adek•4mo ago
I'm checking right now Can you push to the github repo? It's working Thanks! Do you have any advice, where I can improve the code?
Want results from more Discord servers?
Add your server