Zustand
For the client we prefer to use
Zustand
as it is a small bear bones state management solution which is straight forward to use. We are slowly switching from using Redux to using Zustand where this is possible.
The reason being, is we believe, it is far more simpler and intuitive. Setting up Zustand is easy and using it is even more easier!
Hopefully this example will demonstrate this. There are four components here. Each is 'using' the CounterStore which is a Zustand store. If you click the 'Increase' button in the CounterIncrease.tsx component, the counter will increase by one as expected. But only the CounterDisplay.tsx component will be re-rendered as no states have changed in the other components. Note that if the counter is already 5, clicking the 'SetBy (5)' won't re-render anything.
CounterDisplay.tsx
0
CounterSetBy.tsx
CounterIncrease.tsx
CounterDecrease.tsx
These are the corresponding code for each of the four components
CounterDisplay.tsx
import Button from "@/components/Button";
import { useCounterStore } from "./counterStore";

export function CounterDisplay() {
const counter = useCounterStore((state) => state.counter);

return <div>{counter}</div>;
}
CounterSetBy.tsx
import Button from "ui_tailwind/components/Button";
import { useCounterStore } from "./counterStore";

export function CounterSetBy() {
const SetBy = useCounterStore((state) => state.SetBy);

return <Button onClick={() => SetBy(5)}>SetBy (5)</Button>;
}
CounterIncrease.tsx
import Button from "ui_tailwind/components/Button";
import { useCounterStore } from "./counterStore";

export function CounterIncrease() {
const increase = useCounterStore((state) => state.increase);

return <Button onClick={() => increase()}>Increase</Button>;
}
CounterDecrease.tsx
import Button from "ui_tailwind/components/Button";
import { useCounterStore } from "./counterStore";

export function CounterDecrease() {
const decrease = useCounterStore((state) => state.decrease);

return <Button onClick={() => decrease()}>Decrease</Button>;
}
And this is the code for the store
counterStore.ts
import { create } from "zustand";

interface CounterStore {
counter: number;
increase: () => void;
decrease: () => void;
SetBy: (amount: number) => void;
}

export const useCounterStore = create<CounterStore>()((set) => ({
counter: 0,
increase: () => set((state) => ({ counter: state.counter + 1 })),
decrease: () => set((state) => ({ counter: state.counter - 1 })),
SetBy: (amount: number) => set((state) => ({ counter: amount })),
}));
As you can see, it is extremely easy to setup and use. The boilerplate is massively reduced compared to alternatives like Redux.

FUTORO