Pushlished on 03 Jun 2023
Client side state: the state is only limited to client side such as a global menu which is open or closed.
Server side state: this state is both on client and server side such as user's posts, currently logged in user etc.
I like to use library zustand for state management on client side.
Firstly install zustand
npm install zustand
or if you are using yarn
yarn add zustand
Now in src/store/index.ts
import { create } from 'zustand';
interface GlobalState {
count: number;
increment: () => void;
}
const useStore = create<GlobalState>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 }))
}));
Note: zustand also supports async functions for api requests
Now we can access these state and functions in our react app.
const Header: React.FC = () => {
const count = useStore((state) => state.count);
const increment = useStore((state) => state.increment);
// or
const { count, increment } = useState();
// this will result in more rerenders so avoid this
return (
<div>
<h1>{count}</h1>
<button onClick={() => increment()}>Increment</button>
</div>
);
};
To know more about zustand check out zustand's github page
I like to use tanstack react query for server side state management when using rest apis.
Note: tanstack react query can also be used with GraphQL APIs.
Install tanstack react query
npm i @tanstack/react-query @tanstack/react-query-devtools
or if you are using yarn
yarn add @tanstack/react-query @tanstack/react-query-devtools
set up Query Client Provider in index.tsx
import React from 'react';
import App from './App';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
// Create a client
const queryClient = new QueryClient();
const Root: React.FC = () => {
return (
// Provide the client to your App
<QueryClientProvider client={queryClient}>
<App />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
};
render(<Root />, document.getElementById('root'));
Now we can make queries and mutations in App.tsx
import React from 'react';
import { getTodos, postTodo } from './api';
const App: React.FC = () => {
// Access the client
const queryClient = useQueryClient();
// Queries
const { data: todos, isLoading, isError } = useQuery(['todos'], getTodos);
// Mutations
const { mutate: addTodo } = useMutation(['addTodo'], postTodo, {
onSuccess: () => {
// Invalidate and refetch
queryClient.invalidateQueries({ queryKey: ['todos'] });
}
});
if (isLoading || isError || !todos) {
return <p>Loading...</p>;
}
return (
<div>
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
<button
onClick={() => {
addTodo({
id: Date.now(),
title: 'New Todo'
});
}}
>
Add Todo
</button>
</div>
);
};
You should strongly type your getTodos, postTodo from api folder to get better typescript intellisense.
To know more about React Query check out React Query's github page