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•6mo 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
AdekOP•6mo 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
AdekOP•6mo ago
No description
Adek
AdekOP•6mo ago
The second advertisment should look different
Adek
AdekOP•6mo 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•6mo 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
AdekOP•6mo 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
AdekOP•6mo 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•6mo 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
AdekOP•6mo ago
The end result should be this:
No description
Adek
AdekOP•6mo 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•6mo ago
That how it looks for me..
No description
Adek
AdekOP•6mo ago
Sorry, I just got back to PC
Juraj98
Juraj98•6mo ago
(With the new code)
Adek
AdekOP•6mo 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?
Juraj98
Juraj98•6mo ago
Don't have permissions to push into the repo That's kinda broad question, and depends on how much you want to change
Adek
AdekOP•6mo ago
Oh, I think the current solution isn't solved the whole problem, because we need the nextAdvertisment (number, which element of the array ex. 0,1,2) to be used instead of let currentAdIndex = 0; If the solution can solve the problem I would change the whole thing. The idea would be to have a dynamic renderable Advertisment component.
Juraj98
Juraj98•6mo ago
Can you tell me how your API looks? I mean, the one from which you'll be fetching the data
Adek
AdekOP•6mo ago
I created a mock file: components/Advertisment/mock Will be changed but not too much Maybe the approach is bad 😦
Juraj98
Juraj98•6mo ago
Sure, but that tells me just how the data shape looks. I'm more so wondering what is the point of the nextAdvertisementIndex.
Adek
AdekOP•6mo ago
I want to display this ads in multiple places in the same page, let's say I have a Sidebar at left and I want to add some ads there too. So I don't want the same ad in multiple places. The nextAdvertisementIndex should say which ad is next in the list A slider as well ( every 3rd element of the slider should be an ad)
Juraj98
Juraj98•6mo ago
And are you writing the BE also, or is that just some api you're connecting to?
Adek
AdekOP•6mo ago
I will write the backend too(But I'm not quite there). So Idea is that people can have their ads in the application, (like cards, banners, posts, etc.)
Adek
AdekOP•6mo ago
No description
Adek
AdekOP•6mo ago
Maybe this quick draw helps The bottom grid is scrollable So more ads should come in
Juraj98
Juraj98•6mo ago
And everything in the drawing is dynamaic? As in, are you fetching all the categories, slides and grid items?
Adek
AdekOP•6mo ago
Except categories, yes.
Juraj98
Juraj98•6mo ago
And then what's the logic behind where in the categories would the ad be displayed?
Adek
AdekOP•6mo ago
Every third category The same goes to the slider The grid would be somehow dynamic, because it can have multiple dimensions( row-span-2, col-span, etc.)
Juraj98
Juraj98•6mo ago
Okay, got it
Solution
Juraj98
Juraj98•6mo ago
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.
Adek
AdekOP•6mo ago
Yeah, this approach seems more easier. Thanks a lot!!!
Juraj98
Juraj98•6mo ago
🫡
Adek
AdekOP•6mo ago
Thanks for your time, have a good day!
Adek
AdekOP•6mo ago
Just a short question. this endpoints how many Ads should return? The grid is scrollable so there I need "infinite" ads, how can I do that?
Juraj98
Juraj98•6mo ago
It wouldn't be returning "number of ads". It would be returning the items you want to render which would be combination of business cards and ads. For infinite scrolls, you'd be calling the endpoint with properties count and offset, since you can't actually getch infinite amount of data. So for first load you'd have something like count: 50, offset: 0. Then when users scrolls and they want to load more data, you'd call it again with count: 50, offset: 50.
Adek
AdekOP•6mo ago
I got it, thanks!
Want results from more Discord servers?
Add your server