T
TanStack6mo ago
robust-apricot

Migrating Auth0 & React-Router to Tanstack Start or Tanstack React-Router

I'm trying to work through how I can migrate to Tanstack Start but ran into a couple of issues for our Web App. Background: - WebApp written in TypeScript using React-Router (the remix one) - Built using vite and a static index.html - Many libs built custom and used internally are NOT isomorphic => i.e. window.localStorage - Auth0 JS lib doesn't support SSR and I don't want to migrate to Clerk/PropelAuth atm (in future I will) Issues: 1. How to handle client-only libraries i.e. Auth0 JS Ideas: 1. Do I even need SSR => should I just use react-router? (FYI I REALLY want the start functions... but I can bypass in short term) 2. Could I just wrap the <Outlet> with a isClient check and not render (I feel like this will throw hydration error) Any help or guidance is much appreciated. We already migrated our marketing site https://joggr.io and ❤️ it!
Documentation for developers · Joggr
Documentation platform for developers that keeps your documentation up to date.
13 Replies
wise-white
wise-white6mo ago
i could be wrong but i think you disable ssr for anything but not the __root
conscious-sapphire
conscious-sapphire6mo ago
yes, this restriction is correct. we will however lift it once we go for the full SPA mode
robust-apricot
robust-apricotOP6mo ago
@nikus are you saying just wrap in a <ClientOnly> component in the __root.tsx since per @Manuel Schiller pure SPA mode is a no go at this time? @Manuel Schiller tagging you again, but in short term I could just in theory block render using something like <ClientOnly> component (I built something similar to Remix/Next ... I can't rmember which one) but it prevents hydration errors... but Idk about wrapping the <Outlet>
conscious-sapphire
conscious-sapphire6mo ago
yes this how ssr:false works right now just not for the root route but you can just move all the stuff into a route below root
exotic-emerald
exotic-emerald6mo ago
I'd almost prioritise doing the Auth first but then I hate auth0 with a passion
robust-apricot
robust-apricotOP6mo ago
Yes I want to migrate just don't have the time right now.... I'd prefer clerk or propelauth
rare-sapphire
rare-sapphire6mo ago
I have the same issue for "window" in ui library, when try to use "<ClientOnly>" from import { ClientOnly } from "node_modules/@tanstack/react-router/dist/esm/lazyRouteComponent"; I got this error, is this the right way to disable SSR for some parts of code or some routes ? code: <ClientOnly> <Outlet /> </ClientOnly>
No description
conscious-sapphire
conscious-sapphire6mo ago
ssr:false on the route config should do that the component you imported is not exported since it's used internally only
robust-apricot
robust-apricotOP6mo ago
@Mohammed Elsayed FYI I literally just dropped this in another SSR codebase cause I was having issues with things like Prosemirror etc. that manipulate the dom on load =>
import React from 'react';

/**
* Return a boolean indicating if the JS has been hydrated already.
* When doing Server-Side Rendering, the result will always be false.
* When doing Client-Side Rendering, the result will always be false on the
* first render and true from then on. Even if a new component renders it will
* always start with true.
*/
export function useHydrated() {
return React.useSyncExternalStore(
subscribe,
() => true,
() => false
);
}

export interface ClientOnlyProps {
/**
* You are encouraged to add a fallback that is the same dimensions
* as the client rendered children. This will avoid content layout
* shift which is disgusting
*/
children(): React.ReactNode;
fallback?: React.ReactNode;
}

/**
* Render the children only after the JS has loaded client-side. Use an optional
* fallback component if the JS is not yet loaded.
*
* Example: Render a Chart component if JS loads, renders a simple FakeChart
* component server-side or if there is no JS. The FakeChart can have only the
* UI without the behavior or be a loading spinner or skeleton.
*
* @see https://github.com/TanStack/router/blob/main/packages/react-router/src/lazyRouteComponent.tsx#L22C16-L22C27
*/
export function ClientOnly({ children, fallback = null }: ClientOnlyProps) {
return useHydrated() ? (
// biome-ignore lint/complexity/noUselessFragments: We need to prevent rendering issues
<React.Fragment>{children()}</React.Fragment>
) : (
// biome-ignore lint/complexity/noUselessFragments: We need to prevent rendering issues
<React.Fragment>{fallback}</React.Fragment>
);
}

/*
|------------------
| Internals
|------------------
*/

function subscribe() {
return () => {};
}
import React from 'react';

/**
* Return a boolean indicating if the JS has been hydrated already.
* When doing Server-Side Rendering, the result will always be false.
* When doing Client-Side Rendering, the result will always be false on the
* first render and true from then on. Even if a new component renders it will
* always start with true.
*/
export function useHydrated() {
return React.useSyncExternalStore(
subscribe,
() => true,
() => false
);
}

export interface ClientOnlyProps {
/**
* You are encouraged to add a fallback that is the same dimensions
* as the client rendered children. This will avoid content layout
* shift which is disgusting
*/
children(): React.ReactNode;
fallback?: React.ReactNode;
}

/**
* Render the children only after the JS has loaded client-side. Use an optional
* fallback component if the JS is not yet loaded.
*
* Example: Render a Chart component if JS loads, renders a simple FakeChart
* component server-side or if there is no JS. The FakeChart can have only the
* UI without the behavior or be a loading spinner or skeleton.
*
* @see https://github.com/TanStack/router/blob/main/packages/react-router/src/lazyRouteComponent.tsx#L22C16-L22C27
*/
export function ClientOnly({ children, fallback = null }: ClientOnlyProps) {
return useHydrated() ? (
// biome-ignore lint/complexity/noUselessFragments: We need to prevent rendering issues
<React.Fragment>{children()}</React.Fragment>
) : (
// biome-ignore lint/complexity/noUselessFragments: We need to prevent rendering issues
<React.Fragment>{fallback}</React.Fragment>
);
}

/*
|------------------
| Internals
|------------------
*/

function subscribe() {
return () => {};
}
@Manuel Schiller do you think it would be worth exporting? I seem to remember that remix/next.js another has that as a component (happy to open PR)
conscious-sapphire
conscious-sapphire6mo ago
maybe if it's not just a copy of the one from here https://github.com/sergiodxa/remix-utils
GitHub
GitHub - sergiodxa/remix-utils: A set of utility functions and type...
A set of utility functions and types to use with Remix.run - sergiodxa/remix-utils
conscious-sapphire
conscious-sapphire6mo ago
if you want to create a PR make sure to add an e2e test as well as docs
robust-apricot
robust-apricotOP6mo ago
ok will do
robust-apricot
robust-apricotOP6mo ago
GitHub
feat(react-router): Export ClientOnly by zrosenbauer · Pull Requ...
Exposes the ClientOnly component for preventing rendering &amp; hydration errors. Background When you attempt to prevent content from rendering using something like typeof document !== &#39...

Did you find this page helpful?