React アプリケーションを構築する場合、URL に状態を反映すると有益なことがよくあります。これにより、状態が共有可能になるだけでなく、ユーザーがコンテキストを失うことなくページをブックマークしたり更新したりできるようになります。この投稿では、TypeScript で useParamState というカスタム React フックを作成します。このフックは useState と同様に機能しますが、状態と URL 内の検索パラメーターも同期します。重要なのは、複雑なオブジェクト値をサポートすることです。
React Router の useSearchParams フックは、URL 検索パラメータの管理に優れていますが、コンポーネントの状態と同期するのは面倒な場合があります。 useParamState フックは、次のようにしてこれに対処します。
(これは、React プロジェクトのセットアップ方法をすでに知っていることを前提としています。そうでない場合は、Vite に進んでください)
react-router-dom がインストールされていることを確認してください:
npm install react-router-dom
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;
フックは、指定された検索パラメータが URL に存在するかどうかを確認することから始まります。存在する場合、フックはそれを解析し、それを初期状態として使用します。それ以外の場合は、指定されたdefaultValueに戻ります。
setParamState 関数は、内部状態と URL 内の検索パラメータの両方を更新します。 JSON.stringify を使用して状態をシリアル化し、複雑なオブジェクトを URL に保存できるようにします。
フックは、TypeScript のジェネリックスと JSON 解析を活用することで、さまざまな型 (文字列、数値、ブール値、オブジェクト) をサポートします。
React コンポーネントで useParamState を使用する方法を見てみましょう:
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;
useParamState フックが期待どおりに動作することを確認するには、@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' }); });
useParamState フックは、状態を URL 検索パラメータと同期するプロセスを簡素化し、React アプリケーションをより堅牢で使いやすくします。オブジェクトなどの複雑なタイプをサポートするこのフックは、ページのリロード後も保持するか、URL 経由で共有する必要がある状態を管理するための強力なツールです。
このフックをさらに拡張して、さらに複雑なデータ構造を処理することもできますが、ほとんどのユースケースでは、この実装でニーズをカバーできます。
(記事を改善し、間違いを改善できるよう、記事にコメントしてください。よろしくお願いします。)
他のプラットフォームでもお気軽にフォローしてください
リンクトイン
Github
インスタグラム
以上が状態を URL と同期するためのカスタム React フックの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。