TanStackT
TanStack2mo ago
5 replies
brilliant-lime

Relative Navigation with Search Params

I have a parent layout route with this schema:
const ticketFilterSchema = z.object({
  channel: z.array(z.enum(['line', 'facebook', 'instagram'])).catch([]),
  status: z
    .array(z.enum(['new', 'open', 'pending', 'resolved', 'closed']))
    .catch([]),
});

export const Route = createFileRoute('/$tenantId')({
  component: ChatLayout,
  validateSearch: zodValidator(ticketFilterSchema),
});


These filters are configured through a dialog that is triggered from my "chat inbox" that is visible on both /$tenantId and /$tenantId/$userId

Inside of my FilterDialog popup I want to manipulate those search params, which I was doing through useNavigate

const { channel: channels, status: ticketStatuses } = useSearch({
    from: '/$tenantId',
  });
const navigate = useNavigate({ from: '/$tenantId' });


My first instict was to do something like this:

navigate({
                        to: '.',
                        search: prev => ({
                          ...prev,
                          status: checked
                            ? [...prev.status, option.value]
                            : prev.status.filter(v => v !== option.value),
                        }),
                      })


using to as a relative path meaning "current route but with these updated parameters". However it seems like . in this case is linked to that from property of useNavigate, so if I'm on /$tenantId/$userIdit navigates me back to /$tenantId, dropping the selected user and losing UI state.

The simplest fix I found was to remove that from property inside of useNavigate. That's not the worst thing in the world, but I do lose a lot of the strong type guarantees I had before.

Am I missing something with this issue or is there a simple way to get around what I'm looking to do?
Was this page helpful?