Development
Gestion d'État
Guide complet de la gestion d'état dans Company Manager.
Gestion d'État
Guide complet pour gérer l'état de l'application dans Company Manager.
Vue d'Ensemble
Company Manager utilise une combinaison de solutions de gestion d'état :
- Zustand pour l'état global
- React Query pour l'état serveur
- React Hook Form pour l'état des formulaires
- Context API pour l'état partagé local
Zustand
Configuration de Base
// stores/useStore.ts
import { create } from "zustand";
interface Store {
// État
count: number;
user: User | null;
// Actions
increment: () => void;
setUser: (user: User | null) => void;
}
export const useStore = create<Store>((set) => ({
// État initial
count: 0,
user: null,
// Actions
increment: () => set((state) => ({ count: state.count + 1 })),
setUser: (user) => set({ user }),
}));Utilisation
const Component = () => {
const { count, increment } = useStore();
return (
<button onClick={increment}>
Count: {count}
</button>
);
};Slices
// stores/slices/authSlice.ts
interface AuthSlice {
user: User | null;
setUser: (user: User | null) => void;
}
export const createAuthSlice: StateCreator<AuthSlice> = (set) => ({
user: null,
setUser: (user) => set({ user }),
});
// stores/useStore.ts
interface Store extends AuthSlice {
// ... autres slices
}
export const useStore = create<Store>()((...a) => ({
...createAuthSlice(...a),
// ... autres slices
}));React Query
Configuration
// lib/queryClient.ts
import { QueryClient } from "@tanstack/react-query";
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000, // 5 minutes
cacheTime: 10 * 60 * 1000, // 10 minutes
},
},
});Hooks Personnalisés
// hooks/useUsers.ts
export const useUsers = (params: UserParams) => {
return useQuery({
queryKey: ["users", params],
queryFn: () => fetchUsers(params),
select: (data) => data.map(transformUser),
});
};
// hooks/useUpdateUser.ts
export const useUpdateUser = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: updateUser,
onSuccess: (data) => {
queryClient.setQueryData(["user", data.id], data);
queryClient.invalidateQueries(["users"]);
},
});
};Utilisation
const UserList = () => {
const { data, isLoading } = useUsers({ status: 'active' });
const { mutate: updateUser } = useUpdateUser();
if (isLoading) return <Spinner />;
return (
<div>
{data?.map((user) => (
<UserCard
key={user.id}
user={user}
onUpdate={updateUser}
/>
))}
</div>
);
};React Hook Form
Configuration de Base
// components/UserForm.tsx
interface FormData {
name: string;
email: string;
role: string;
}
const UserForm = () => {
const form = useForm<FormData>({
defaultValues: {
role: 'user',
},
resolver: zodResolver(userSchema),
});
const onSubmit = async (data: FormData) => {
await createUser(data);
};
return (
<Form {...form}>
<FormField
name="name"
label="Nom"
control={form.control}
/>
{/* ... autres champs */}
</Form>
);
};Validation
// schemas/userSchema.ts
import { z } from "zod/v4";
export const userSchema = z.object({
name: z.string().min(2),
email: z.string().email(),
role: z.enum(["user", "admin"]),
});Context API
Création du Contexte
// contexts/ThemeContext.tsx
interface ThemeContextType {
theme: Theme;
setTheme: (theme: Theme) => void;
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
export const ThemeProvider: FC<PropsWithChildren> = ({ children }) => {
const [theme, setTheme] = useState<Theme>('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within ThemeProvider');
}
return context;
};Persistence
Local Storage
// stores/usePersistedStore.ts
import { persist } from "zustand/middleware";
export const usePersistedStore = create(
persist(
(set) => ({
settings: defaultSettings,
updateSettings: (settings: Settings) => set({ settings }),
}),
{
name: "settings-storage",
}
)
);Bonnes Pratiques
-
Sélection de l'Outil
- Zustand pour l'état global simple
- React Query pour les données serveur
- Context pour l'état partagé local
- Local state pour l'état composant
-
Performance
- Éviter le re-render inutile
- Utiliser la mémoisation
- Optimiser les sélecteurs
-
Organisation
- Structure claire des stores
- Séparation des préoccupations
- Documentation des interfaces