Beim Erstellen von React-Anwendungen ist es oft von Vorteil, den Status in der URL wiederzugeben. Dies macht den Status nicht nur gemeinsam nutzbar, sondern ermöglicht es Benutzern auch, Seiten mit Lesezeichen zu versehen oder zu aktualisieren, ohne dass der Kontext verloren geht. In diesem Beitrag erstellen wir einen benutzerdefinierten React-Hook namens useParamState in TypeScript. Dieser Hook funktioniert wie useState, synchronisiert jedoch auch den Status mit den Suchparametern in der URL. Wichtig ist, dass es komplexe Objektwerte unterstützt.
Der useSearchParams-Hook von React Router eignet sich hervorragend zum Verwalten von URL-Suchparametern, ihre Synchronisierung mit dem Komponentenstatus kann jedoch umständlich sein. Der useParamState-Hook behebt dies durch:
(Dies setzt voraus, dass Sie bereits wissen, wie man ein Reaktionsprojekt einrichtet, wenn nicht, gehen Sie zu Vite)
Stellen Sie sicher, dass Sie „react-router-dom“ installiert haben:
npm install react-router-dom
So können Sie den useParamState-Hook implementieren:
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;
Der Hook prüft zunächst, ob der angegebene Suchparameter in der URL vorhanden ist. Wenn dies der Fall ist, analysiert der Hook es und verwendet es als Anfangszustand. Andernfalls wird auf den bereitgestellten Standardwert zurückgegriffen.
Die Funktion setParamState aktualisiert sowohl den internen Status als auch den Suchparameter in der URL. Es verwendet JSON.stringify, um den Status zu serialisieren, sodass wir komplexe Objekte in der URL speichern können.
Der Hook unterstützt verschiedene Typen (String, Zahl, Boolescher Wert und Objekt), indem er die Generika von TypeScript und die JSON-Analyse nutzt.
Sehen wir uns an, wie Sie useParamState in einer React-Komponente verwenden können:
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;
Um sicherzustellen, dass der useParamState-Hook wie erwartet funktioniert, können Sie Unit-Tests mit @testing-library/react:
schreiben
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' }); });
Der useParamState-Hook vereinfacht die Synchronisierung des Status mit URL-Suchparametern und macht Ihre React-Anwendungen robuster und benutzerfreundlicher. Mit der Unterstützung für komplexe Typen wie Objekte ist dieser Hook ein leistungsstarkes Tool zum Verwalten des Status, der über das erneute Laden von Seiten hinweg bestehen bleiben oder über URLs geteilt werden muss.
Sie können diesen Hook weiter erweitern, um noch komplexere Datenstrukturen zu verarbeiten, aber für die meisten Anwendungsfälle wird diese Implementierung Ihre Anforderungen abdecken.
(Kommentieren Sie den Artikel, damit ich ihn verbessern und eventuelle Fehler korrigieren kann. Vielen Dank im Voraus.)
Folge mir gerne auch auf anderen Plattformen
Github
Das obige ist der detaillierte Inhalt vonBenutzerdefinierter React-Hook zum Synchronisieren des Status mit der URL. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!