首頁 > web前端 > js教程 > 主體

自訂 React hook 以將狀態與 URL 同步

PHPz
發布: 2024-08-10 18:53:32
原創
994 人瀏覽過

Custom React hook to sync state with the URL

建立 React 應用程式時,在 URL 中反映狀態通常很有用。這不僅使狀態可共享,還允許用戶在不丟失上下文的情況下添加書籤或刷新頁面。在這篇文章中,我們將在 TypeScript 中建立一個名為 useParamState 的自訂 React 鉤子。這個鉤子的功能類似於 useState,但它也會將狀態與 URL 中的搜尋參數同步。重要的是,它將支援複雜的物件值。

為什麼要使用ParamState?

React Router 的 useSearchParams 鉤子非常適合管理 URL 搜尋參數,但將它們與元件狀態同步可能很麻煩。 useParamState 鉤子透過以下方式解決這個問題:

  • 提供類似useState的簡單API。
  • 自動將狀態與 URL 搜尋參數同步。
  • 支援複雜類型,包括物件。

先決條件

  • 對 React、TypeScript 和 React Router 的基本了解。
  • 熟悉 useState 和 useEffect。

實作 useParamState

第 1 步:設定項目

(這假設你已經知道如何建立一個 React 項目,如果你不知道如何去 Vite)

確保你已經安裝了react-router-dom:

npm install react-router-dom
登入後複製

步驟 2:useParamState 掛鉤

以下是實作 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 中是否存在指定的搜尋參數。如果是,鉤子會解析它並將其用作初始狀態。否則,它將回退到提供的預設值。

狀態更新:

setParamState 函數會更新內部狀態和 URL 中的搜尋參數。它使用 JSON.stringify 來序列化狀態,讓我們在 URL 中儲存複雜的物件。

類型支援:

該鉤子透過利用 TypeScript 的泛型和 JSON 解析來支援各種類型(字串、數字、布林值和物件)。

第三步:使用useParamState

讓我們看看如何在 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;

登入後複製

第 4 步:測試 Hook

為了確保 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 共享的狀態。

您可以進一步擴展此鉤子以處理更複雜的資料結構,但對於大多數用例,此實作將滿足您的需求。

(請對文章發表評論,以便我可以做得更好並改進我可能犯的任何錯誤,提前感謝。)

也歡迎在其他平台追蹤我

  • Linkedin

  • Github

  • Instagram

以上是自訂 React hook 以將狀態與 URL 同步的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!