Skip to content

Instantly share code, notes, and snippets.

@dantldev
Created February 23, 2024 21:43
Show Gist options
  • Save dantldev/32ce425c8f4062eb6e84af38f878bc73 to your computer and use it in GitHub Desktop.
Save dantldev/32ce425c8f4062eb6e84af38f878bc73 to your computer and use it in GitHub Desktop.
zustand quick docs
/**
* live demo https://codesandbox.io/p/devbox/confident-bessie-ldx396?file=%2Fsrc%2FApp.tsx%3A1%2C34&layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clsz5b2c400073j6j1kpfsrwy%2522%252C%2522sizes%2522%253A%255B100%252C0%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clsz5b2c300023j6jdruu5tjb%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clsz5b2c300043j6jyrkssxg1%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clsz5b2c400063j6j2ehb6ut9%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B69.75503441746712%252C30.244965582532885%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clsz5b2c300023j6jdruu5tjb%2522%253A%257B%2522id%2522%253A%2522clsz5b2c300023j6jdruu5tjb%2522%252C%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clsz5f5j700023j6j4pq4ijc8%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522initialSelections%2522%253A%255B%257B%2522startLineNumber%2522%253A1%252C%2522startColumn%2522%253A34%252C%2522endLineNumber%2522%253A1%252C%2522endColumn%2522%253A34%257D%255D%252C%2522filepath%2522%253A%2522%252Fsrc%252FApp.tsx%2522%252C%2522state%2522%253A%2522IDLE%2522%257D%255D%252C%2522activeTabId%2522%253A%2522clsz5f5j700023j6j4pq4ijc8%2522%257D%252C%2522clsz5b2c400063j6j2ehb6ut9%2522%253A%257B%2522id%2522%253A%2522clsz5b2c400063j6j2ehb6ut9%2522%252C%2522tabs%2522%253A%255B%257B%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A5173%252C%2522id%2522%253A%2522clsz5foqi007b3j6j0wjer37l%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522path%2522%253A%2522%252F%2522%257D%255D%252C%2522activeTabId%2522%253A%2522clsz5foqi007b3j6j0wjer37l%2522%257D%252C%2522clsz5b2c300043j6jyrkssxg1%2522%253A%257B%2522id%2522%253A%2522clsz5b2c300043j6jyrkssxg1%2522%252C%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clsz5bmy8008t3j6jrbhvqcl8%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522TERMINAL%2522%252C%2522shellId%2522%253A%2522clsz5bn7h020rdcip7k97asgz%2522%257D%255D%252C%2522activeTabId%2522%253A%2522clsz5bmy8008t3j6jrbhvqcl8%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Afalse%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D
**/
import { createStore, useStore } from "zustand";
import { immer } from "zustand/middleware/immer";
/**
* Note: its a good idea to define the type of the store
* so on another file you can import it and use it
*/
export interface MainStore {
user: {
id: number;
name: string;
} | null;
}
/**
* same with the actions
*/
export interface MainStoreActions {
setUser: (args: MainStore["user"]) => void;
}
const initialState: MainStore = {
user: null,
};
export const MainStore = createStore(
// immer is very cool to not have to spread the state all the time
immer<MainStore & MainStoreActions>(
(set, get /** you dont use much get here */) => ({
...initialState,
// here you can define whatever you want async or not. It doesnt matter.
setUser: (newValues) => {
set((state) => {
state.user = newValues;
});
},
/*
// define functions outside this scope is a little weird, maybe you can came up with something else
foo: (newValues) => {
functionOnAnotherFile(newValues, set, get);
}
// you can be tempted to set this in another file. But remember. You can have any number of stores so,
// it doesnt matter that much. You can do it here.
// you can make computed values
getNameInUppercase: () => {
const user = get().user;
return user ? user.name.toUpperCase() : "";
}
*/
}),
),
);
// export the store as a custom hook
export const useMainStore = () => {
return useStore(MainStore);
};
// using the store outside a component to set state
export const setUser = () => {
MainStore.setState((state) => {
state.user = { id: 1, name: "test" };
});
};
export const removeUser = () => {
MainStore.setState((state) => {
state.user = null;
});
};
// using the store outside a component to get state
export const getUser = MainStore.getState().user;
// making function and stuffs (if needed, but is better to stay inside the MainStore definition (above) so you dont
// mess up with disconnected proxies from immer and that kind of stuff)
export const getUserOrRedirect = () => {
const user = MainStore.getState().user;
if (!user) {
// do your redirect thing
return null;
}
return user;
};
// usage on a react component
import { removeUser, setUser, useMainStore } from "./store/main.store";
import "./App.css";
function App() {
const { user } = useMainStore();
if (!user) {
return (
<>
<p>no user no party</p>
<button onClick={setUser}>set a user</button>
</>
);
}
return (
<>
<p>hello {user.name}</p>
<button onClick={removeUser}>remove the user (logout)</button>
</>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment