T
TanStack11mo ago
correct-apricot

how can I match a route with same component and not rerender?

I want to render my /login and /register pages with the same component. the router should render the same component but only change disabled properties on input fields and toggle this className on an overlay div. simple recreation:
function RouteComponent() {
const isLoginPage = getIsLoginPage(); // match based on url being /login or /register

const togglePage = () => {
// toggle between login/register
}

return (
<div className="flex">
<div
className={cn(
"w-1/2 absolute top-0 h-full",
isLoginPage ? "left-0" : "left-1/2"
)}
>
<button>{isLoginPage ? "Register" : "Login"}</button>
</div>
<form>
<input name="username" disabled={!isLoginPage} />
<input name="password" disabled={!isLoginPage} />
<button type="submit" disabled={!isLoginPage}>
login
</button>
</form>
<form>
<input name="username" disabled={!isLoginPage} />
<input name="password" disabled={!isLoginPage} />
<button type="submit" disabled={!isLoginPage}>
register
</button>
</form>
</div>
)
}
function RouteComponent() {
const isLoginPage = getIsLoginPage(); // match based on url being /login or /register

const togglePage = () => {
// toggle between login/register
}

return (
<div className="flex">
<div
className={cn(
"w-1/2 absolute top-0 h-full",
isLoginPage ? "left-0" : "left-1/2"
)}
>
<button>{isLoginPage ? "Register" : "Login"}</button>
</div>
<form>
<input name="username" disabled={!isLoginPage} />
<input name="password" disabled={!isLoginPage} />
<button type="submit" disabled={!isLoginPage}>
login
</button>
</form>
<form>
<input name="username" disabled={!isLoginPage} />
<input name="password" disabled={!isLoginPage} />
<button type="submit" disabled={!isLoginPage}>
register
</button>
</form>
</div>
)
}
9 Replies
foreign-sapphire
foreign-sapphire11mo ago
check useMatches
correct-apricot
correct-apricotOP11mo ago
heres a codesandbox, got it to work. I handle everything in the _auth.lazy.tsx component, which is kinda weird, but it works. LMK if you got a better solution https://codesandbox.io/p/github/zdenkolini/tanstack-router-single-route-auth/main?import=true
foreign-sapphire
foreign-sapphire11mo ago
just a hint, you don't need to use lazy anymore with automatic codesplitting
correct-apricot
correct-apricotOP11mo ago
other than that, you wouldn't change anything?
foreign-sapphire
foreign-sapphire10mo ago
i personally would pass the route I am on via a prop into the component if it is just two routes, why complicate things
correct-apricot
correct-apricotOP10mo ago
so if I understand this right, just create a child component that takes in the isLoginRoute boolean as a prop and keep the router setup regarding route definitions and isLoginRoute boolean derivation logic? IMO there should be an example or functionality of defining possible options for url parameters for example /auth/:page(login|register) to register 2 routes that render the same component
correct-apricot
correct-apricotOP10mo ago
here is an example of such a route for react router v5 https://v5.reactrouter.com/web/api/generatePath
ReactRouterWebsite
React Router: Declarative Routing for React
Learn once, Route Anywhere
correct-apricot
correct-apricotOP10mo ago
via the current docs, I think this is possible to achieve with a loader that will throw notFound() if the url parameter is not one of the 2 :pages. I'll update the sandbox and get back to you to showcase what I mean
foreign-sapphire
foreign-sapphire10mo ago
contributions are always welcome!

Did you find this page helpful?