Lors de la création d'applications React, il est souvent avantageux de refléter l'état dans l'URL. Cela rend non seulement l'état partageable, mais permet également aux utilisateurs de mettre en signet ou d'actualiser des pages sans perdre leur contexte. Dans cet article, nous allons créer un hook React personnalisé appelé useParamState dans TypeScript. Ce hook fonctionnera comme useState, mais il synchronisera également l'état avec les paramètres de recherche dans l'URL. Surtout, il prendra en charge les valeurs d'objets complexes.
Le hook useSearchParams de React Router est excellent pour gérer les paramètres de recherche d'URL, mais les synchroniser avec l'état des composants peut être fastidieux. Le hook useParamState résout ce problème par :
(Cela suppose que vous savez déjà comment mettre en place un projet React, sinon rendez-vous sur Vite)
Assurez-vous que React-Router-Dom est installé :
npm install react-router-dom
Voici comment implémenter le hook useParamState :
import { useCallback, useState } from 'react'; import { useSearchParams } from 'react-router-dom'; /** * A custom hook that syncs state with a URL search parameter. * Supports string, number, boolean, and object values. * @param key The search parameter key to sync with. * @param defaultValue The default value for the state. * @returns A stateful value, and a function to update it. */ function useParamState<T extends string | number | boolean | object>( key: string, defaultValue: T ): [T, (newValue: Partial<T> | T) => void] { const [searchParams, setSearchParams] = useSearchParams(); const paramValue = searchParams.get(key); const [state, setState] = useState<T>(() => { if (paramValue === null) { return defaultValue; } try { return JSON.parse(paramValue) as T; } catch { return paramValue as T; } }); const setParamState = useCallback( (newValue: Partial<T> | T) => { const updatedValue = typeof newValue === 'object' && !Array.isArray(newValue) ? { ...state, ...newValue } : newValue; setState(updatedValue as T); const newSearchParams = new URLSearchParams(searchParams); newSearchParams.set(key, JSON.stringify(updatedValue)); setSearchParams(newSearchParams); }, [key, searchParams, setSearchParams, state] ); return [state, setParamState]; } export default useParamState;
Le hook commence par vérifier si le paramètre de recherche spécifié existe dans l'URL. Si c’est le cas, le hook l’analyse et l’utilise comme état initial. Sinon, il revient à la valeur par défaut fournie.
La fonction setParamState met à jour à la fois l'état interne et le paramètre de recherche dans l'URL. Il utilise JSON.stringify pour sérialiser l'état, nous permettant de stocker des objets complexes dans l'URL.
Le hook prend en charge différents types (chaîne, nombre, booléen et objet) en tirant parti des génériques de TypeScript et de l'analyse JSON.
Voyons comment utiliser useParamState dans un composant React :
import React from 'react'; import useParamState from './useParamState'; interface FilterState { status: string; sortBy: string; } const MyComponent: React.FC = () => { const [filter, setFilter] = useParamState<FilterState>('filter', { status: 'all', sortBy: 'date', }); return ( <div> <h2>Current Filter: {filter.status}, Sort by: {filter.sortBy}</h2> <button onClick={() => setFilter({ status: 'active', sortBy: filter.sortBy })}> Active </button> <button onClick={() => setFilter({ status: 'completed', sortBy: filter.sortBy })}> Completed </button> <button onClick={() => setFilter({ ...filter, sortBy: 'priority' })}> Sort by Priority </button> </div> ); }; export default MyComponent;
Pour vous assurer que le hook useParamState fonctionne comme prévu, vous pouvez écrire des tests unitaires en utilisant @testing-library/react :
import { renderHook, act } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; import useParamState from './useParamState'; interface FilterState { status: string; sortBy: string; } test('should sync object state with search params', () => { const wrapper = ({ children }: { children: React.ReactNode }) => ( <MemoryRouter initialEntries={['/']}>{children}</MemoryRouter> ); const { result } = renderHook(() => useParamState<FilterState>('filter', { status: 'all', sortBy: 'date' }), { wrapper }); // Initial state expect(result.current[0]).toEqual({ status: 'all', sortBy: 'date' }); // Update state and URL act(() => { result.current[1]({ status: 'active', sortBy: 'priority' }); }); // Updated state expect(result.current[0]).toEqual({ status: 'active', sortBy: 'priority' }); });
Le hook useParamState simplifie le processus de synchronisation de l'état avec les paramètres de recherche d'URL, rendant vos applications React plus robustes et conviviales. Avec la prise en charge de types complexes tels que les objets, ce hook est un outil puissant pour gérer l'état qui doit persister lors des rechargements de page ou être partagé via des URL.
Vous pouvez étendre davantage ce hook pour gérer des structures de données encore plus complexes, mais pour la plupart des cas d'utilisation, cette implémentation couvrira vos besoins.
( Commentez l'article pour que je puisse l'améliorer et améliorer les erreurs que j'aurais pu commettre, merci d'avance. )
N'hésitez pas à me suivre également sur d'autres plateformes
Github
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!