Skip to content

docs: Add inertia community adapter #787

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: next
Choose a base branch
from
Open

Conversation

Joehoel
Copy link

@Joehoel Joehoel commented Nov 28, 2024

This PR adds documentation for a community adapter for Inertia.js. Inspired by the conversations on X. Related #786

Copy link

vercel bot commented Nov 28, 2024

@Joehoel is attempting to deploy a commit to the 47ng Team on Vercel.

A member of the Team first needs to authorize it.

@Joehoel
Copy link
Author

Joehoel commented Nov 28, 2024

Also might be related: inertiajs/inertia#2110

While creating the adapter I was facing some issues with persistent layouts from inertia and the state not updating correctly. Anyone face similar issues?

@franky47
Copy link
Member

Echoing my inertiajs/inertia#2110 (comment), the key thing for adapters to work is that the searchParams value returned be reactive to URL changes, no matter where they originate from (nuqs itself, Link components, imperative router calls, calls to history.replaceState by 3rd party code etc).

This is unfortunately not an easy thing to do, and it looks like most adapters (apart from Next.js which does some of that for us) need to do the same kind of heavy lifting work to get this reactive value.

Copy link

vercel bot commented Nov 28, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
nuqs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 28, 2024 8:16pm

@Joehoel
Copy link
Author

Joehoel commented Nov 28, 2024

Thanks for clarifying. I can look into it when I have some extra time but if someone else wants to have a stab!

Maybe we can take some inspiration from the remix/react-router code for the reactive search params?

@franky47
Copy link
Member

franky47 commented Nov 28, 2024

I have some updates for the Remix adapter that I need to test & push, it's adding a lot of those things I mentioned but it could probably be refactored to benefit a lot of other adapters. I might have more time to work on that next week.

@Joehoel
Copy link
Author

Joehoel commented Nov 29, 2024

Just realised Inertia has a usePage hook.

import { router, usePage } from "@inertiajs/react";
import {
  type unstable_AdapterOptions as AdapterOptions,
  unstable_createAdapterProvider as createAdapterProvider,
  renderQueryString,
} from "nuqs/adapters/custom";

function useNuqsInertiaAdapter() {
  const { searchParams } = new URL(location.origin + usePage().url);

  function updateUrl(search: URLSearchParams, options: AdapterOptions) {
    const url = new URL(location.href);
    url.search = renderQueryString(search);
    router.visit(url, {
      replace: options.history === "replace",
      preserveScroll: !options.scroll,
      preserveState: options.shallow,
    });
  }
  return {
    searchParams,
    updateUrl,
  };
}

export const NuqsAdapter = createAdapterProvider(useNuqsInertiaAdapter);

Implemented this is my test app and it works and fixes this issue inertiajs/inertia#2110 (comment)

@franky47
Copy link
Member

Looks good! However I think the shallow option doesn't really map to Inertia's state preservation mechanism.

In nuqs, shallow: true (the default) means we should only update the client-side application when a search param changes (using the history API), and the server is not called. Setting shallow: false opts-in to calling the server for search params that do need to be read server-side.

The history API part is also something that could be factored out of all of those adapters.

@franky47 franky47 added the documentation Improvements or additions to documentation label Dec 1, 2024
@franky47 franky47 added the adapters/community Custom community-provided adapters label Jan 6, 2025
@franky47 franky47 changed the title Add inertia community adapter docs docs: Add inertia community adapter docs Feb 1, 2025
@franky47 franky47 changed the title docs: Add inertia community adapter docs docs: Add inertia community adapter Feb 1, 2025
@thewebartisan7
Copy link

@Joehoel will this PR be merged?

@franky47
Copy link
Member

franky47 commented May 6, 2025

@thewebartisan7 considering this is a documentation-only update, have you tried the suggested code? My concern was that it doesn't satisfy the shallow option, which should:

  • Update search params client-side only by default
  • Notify the server (whatever that means in this case) when setting shallow: false

@thewebartisan7
Copy link

@thewebartisan7 considering this is a documentation-only update, have you tried the suggested code? My concern was that it doesn't satisfy the shallow option, which should:

  • Update search params client-side only by default
  • Notify the server (whatever that means in this case) when setting shallow: false

I did test it, and it seems to work fine for me using the version @Joehoel suggested with usePage().url:

const { searchParams } = new URL(location.origin + usePage().url);

I also tested it using just router.reload(), which reloads the current URL, and that also appears to work well. Here's an example:

import { router, usePage } from "@inertiajs/react";
import {
    unstable_createAdapterProvider as createAdapterProvider,
} from "nuqs/adapters/custom";

function useNuqsInertiaAdapter() {
    const url = usePage().url
    const { searchParams } = new URL(location.origin + url);
    function updateUrl() {
        router.reload()
    }
    return {
        searchParams,
        updateUrl,
    };
}

export const NuqsAdapter = createAdapterProvider(useNuqsInertiaAdapter);

I tested this in a repo that uses a persistent layout, which seems to be where the issue arises:
https://github.com/thewebartisan7/inertia-nuqs/blob/main/resources/js/layouts/layout.tsx

I don’t have much experience with nuqs, but based on my testing, it seems to work as expected. The search params appear to stay in sync with the Inertia state. Both router.reload() and router.visit() seem to do the trick.

One thing different from @Joehoel example is that I wrap top level App component around NuqsAdapter, see:

    setup({ el, App, props }) {
        const root = createRoot(el);

        root.render(<NuqsAdapter><App {...props} /></NuqsAdapter>);
    },

But it's not clear here inertiajs/inertia#2110 (comment) how he created the persistent layout since according to Inertia docs it must be set in resolve().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
adapters/community Custom community-provided adapters documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants