Inertia

将 nuqs 与 Inertia 集成

Inertia 通过社区贡献的适配器支持。

试试看

查看 demo app, 这是 Inertia 的 Ping CRM demo 的一个 fork,集成了 nuqs。

步骤 1:添加适配器代码

自定义适配器 API 尚未稳定,未来可能会在 次要或补丁版本中发生变化(不遵循 SemVer)。

TypeScript
resources/js/lib/nuqs-inertia-adapter.ts
import { router, usePage } from '@inertiajs/react';
import {
  unstable_createAdapterProvider as createAdapterProvider,
  renderQueryString,
  type unstable_AdapterInterface as AdapterInterface,
  type unstable_AdapterOptions as AdapterOptions,
  type unstable_UpdateUrlFunction as UpdateUrlFunction
} from 'nuqs/adapters/custom';
import * as React from 'react';
import { useEffect } from 'react';

function useNuqsInertiaAdapter(): AdapterInterface {
  const currentUrl = usePage().url;
  // We need the searchParams to be optimistic to avoid
  // flickering when the internal state is updated
  // but the URL is not yet updated.
  const [searchParams, setSearchParams] = React.useState(
    new URL(`${location.origin}${currentUrl}`).searchParams
  );

  useEffect(() => {
    setSearchParams(new URL(`${location.origin}${currentUrl}`).searchParams);
  }, [currentUrl]);

  const updateUrl: UpdateUrlFunction = React.useCallback(
    (search: URLSearchParams, options: AdapterOptions) => {
      const url = new URL(window.location.href);
      url.search = renderQueryString(search);
      setSearchParams(url.searchParams);

      // Server-side request
      if (options?.shallow === false) {
        router.visit(url, {
          replace: options.history === 'replace',
          preserveScroll: !options.scroll,
          preserveState: true,
          async: true
        });
        return;
      }

      const method = options.history === 'replace' ? 'replace' : 'push';

      router[method]({
        url: url.toString(),
        clearHistory: false,
        encryptHistory: false,
        preserveScroll: !options.scroll,
        preserveState: true
      });
    },
    []
  );

  return {
    searchParams,
    updateUrl
  };
}

export const NuqsAdapter = createAdapterProvider(useNuqsInertiaAdapter);

步骤 2:创建新的全局应用布局

将适配器集成到根布局文件中,通过将布局组件的子元素 包裹在其中:

resources/js/Layouts/AppLayout.tsx
import { NuqsAdapter } from '.@/lib/nuqs-inertia-adapter'
import { PropsWithChildren } from 'react'

export default function Layout({ children }: PropsWithChildren) {
  return <NuqsAdapter>{children}</NuqsAdapter>
}