Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

rocketpanda's avatar

Persisent children with tabbed pages with Inertia.js and React

I am trying to implement tabbed pages with Inertia.js and React. An example of this is seen when managing tickets in Zendesk. You can have multiple tickets open at the same time, switching between them while the URL updates, but the state of each tickets you're working on is kept.

The thing I'm having trouble figuring out is how to keep the state of each page while making a page visit, like an inverted persistent layout, if that makes sense. Using the useRememberedState hook isn't the answer, as it only pertains to the browser history. The best case scenario, as I see it, is to keep all page components rendered on the page between page visits. Also, open tabs are saved in the database and passed through to Inertia.js with each visit.

I may be thinking about this all wrong, but I'm not really sure about how I should approach this. Would love to hear your thoughts on this.

0 likes
7 replies
Sinnbeck's avatar

How does the url update? Hashes? And could you perhaps nest your remembered state?

{
   tabname1: {
     name: null,
   },
    tabname2: {
      name: null
   },
rocketpanda's avatar

The URL updates by a regular page visits. I'd like to keep the history state and not use a hash.

Here is a simplified version of what I've started with (which I should've included, sorry about that!), just to get something on the page:

// TicketLayout.jsx
import React from 'react'
import {InertiaLink} from "@inertiajs/inertia-react";

const TicketLayout = ({ children, tabs }) => {
    return (
	<>
            <div className="flex h-16 border-b flex bg-white">
                <InertiaLink href="/desk/tickets" className="flex items-center h-full px-5 font-semibold border-r hover:bg-gray-50">
                    Alle
                </InertiaLink>
                <ul className="flex">
                    {tabs.map(tab => (
                        <li key={tab.id}>
                            <InertiaLink href={tab.url} className="h-full flex items-center px-5 border-r font-medium">
                                {tab.title}
                            </InertiaLink>
                        </li>
                    ))}
                </ul>
            </div>
            {children}
	</>
    )
}

export default TicketLayout

// ShowTicket.jsx
import React, { useState } from 'react'
import TicketLayout from "./TicketLayout";
import { Inertia } from "@inertiajs/inertia";
import { useRememberedState } from '@inertiajs/inertia-react'

const TicketIndex = ({ ticket, tabs }) => {
    const [value, setValue] = useRememberedState(
        '',
        `/ShowTicket:${ticket.id}`
    )

    return (
        <div className="flex">
            <div className="w-80">
                Aktivitet
            </div>
            <div className="flex-1 p-10">
                <div className="bg-white rounded-md shadow">
                    {ticket.title}
                    <input
			type="text"
                        value={value}
                        onChange={(e) => setValue(e.target.value)}
                    />
                </div>
            </div>
        </div>
    )
}

ShowTicket.layout = page => {
    return <TicketLayout children={page} tabs={page.props.tabs} />
}

export default ShowTicket
Sinnbeck's avatar

Danish? :)

You are correct that it only persists to the history. I am quite certain that this will not change in Inertia.

Perhaps using localStorage could be used for saving temporatory values?

rocketpanda's avatar

Almost, Norwegian :) I was thinking about using localStorage, and it might turn out to be the best solution. I just really wished there were a way to solve this just by utilizing what Inertia.js offers. I'm a bit sleep deprived while of paternity leave, so I'm just really struggling to see all the options.

Sinnbeck's avatar

I know the feeling.

I agree. I suggest localStorage. I was at an online meetup with Jonathan Reinink where he talked about persistence and seemed very happy that it was in browser history only, so I dont think he is going to make any changes to it. You can try adding an issue to the github page, and see if he is interested, but I would assume not.

rocketpanda's avatar

I think it's outside of the scope of Intertia.js anyway. We're probably too spoiled already. One way to make (think about) this would've been to have multiple components, one for each page, and just switching between them based on page visits, but I can't see any clever way to make that happen. An alternate approach may be to keep the state of all the tickets in the persistent layout and using something like Zustand to manage it, updating it on every page load to add another tab. I don't know exactly how Inertia.js works internally, so and I'm not even sure if that is possible.

rocketpanda's avatar

So, a little update on this issue, in case other people ends up reading this thread. I ended up hacking something together using Zustand in a persistent layout. Whenever a page loads, tabs (which are stored in a JSON column) is updated from the page component. For each page I keep a record of local state with Zustand instead of keeping it in page component.

It doesn't "feel" like a good solution, but there might be better a solution coming to Inertia.js. Jonathan Reinink just tweeted about something called inline page components which looks like it might be a better, "native" solution. It's no wonder I love Inertia.js and the work of Reinink and contributors!

Please or to participate in this conversation.