skip to Main Content

Basically, I have 3 pages (or 2 routes) in my Remix app:

  1. /login – Login
  2. / – Sign Up (if unauthenticated)
  3. / – Dashboard (if authenticated)

How do I make sure to show Dashboard on / route if authenticated & show Sign Up if unauthenticated?

The answer on here is pretty close but I want to figure out what to do with Outlet?

root.tsx

import type { LinksFunction, LoaderFunctionArgs } from "@remix-run/node"
import {
    Links,
    LiveReload,
    Meta,
    Outlet,
    Scripts,
    ScrollRestoration,
    useLoaderData,
} from "@remix-run/react"

import styles from "./styles/tailwind.css"

export const links: LinksFunction = () => [
    {
        rel: "stylesheet",
        href: styles,
    },
]

export const loader = async ({ request }: LoaderFunctionArgs) => {
    const isAuthenticated = false // getAuthenticatedUser(request)

    if (isAuthenticated) {
        // run code to get user home page data and return a response
        return {
            type: "dashboard",
        }
    }

    // run code to get the public data and return a response
    return {
        type: "signup",
    }
}

const SignUp = () => (
    <>
        <h1>SignUp</h1>
    </>
)

const Dashboard = () => (
    <>
        <h1>Dashboard</h1>
    </>
)

const App = () => {
    const loaderData = useLoaderData<typeof loader>()

    return (
        <html lang="en">
            <head>
                <meta charSet="utf-8" />
                <meta name="viewport" content="width=device-width, initial-scale=1" />
                <Meta />
                <Links />
            </head>
            <body>
                <Outlet />
                {loaderData.type === "signup" ? <SignUp /> : <Dashboard />}
                <ScrollRestoration />
                <Scripts />
                <LiveReload />
            </body>
        </html>
    )
}

export default App

2

Answers


  1. Chosen as BEST ANSWER

    Mayank gave the answer but its a bit confusing as he used different variables so I'm posting it here in detail with filenames similar to the original question.

    root.tsx

    import type { LinksFunction } from "@remix-run/node"
    import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react"
    
    import styles from "./styles/tailwind.css"
    
    export const links: LinksFunction = () => [
        {
            rel: "stylesheet",
            href: styles,
        },
    ]
    
    const App = () => {
        return (
            <html lang="en">
                <head>
                    <title>My App</title>
                    <meta charSet="utf-8" />
                    <meta name="viewport" content="width=device-width, initial-scale=1" />
                    <Meta />
                    <Links />
                </head>
                <body>
                    <Outlet />
                    <ScrollRestoration />
                    <Scripts />
                    <LiveReload />
                </body>
            </html>
        )
    }
    
    export default App
    

    routes/_index.tsx

    You can toggle isAuthenticated by removing the ! to see the dashboard page.

    import { json, type LoaderFunctionArgs } from "@remix-run/node"
    import { useLoaderData } from "@remix-run/react"
    
    import Dashboard from "./dashboard"
    import SignUp from "./signup"
    
    export const loader = async ({ request }: LoaderFunctionArgs) => {
        const isAuthenticated = !true // getAuthenticatedUser(request)
    
        return json({
            isAuthenticated,
        })
    }
    
    const Home = () => {
        const loaderData = useLoaderData<typeof loader>()
    
        if (loaderData.isAuthenticated) return <Dashboard />
        return <SignUp />
    }
    
    export default Home
    

    routes/dashboard.tsx

    const Dashboard = () => (
        <>
            <h1>Dashboard</h1>
        </>
    )
    
    export default Dashboard
    

    routes/signup.tsx

    const SignUp = () => (
        <>
            <h1>SignUp</h1>
        </>
    )
    
    export default SignUp
    

    This shows SignUp & Dashboard page on the same route /. The most confusing part to me was Outlet but I think removing the code from root.tsx into routes/_index.tsx solved the problem.


  2. Loader in Remix runs on the server side, so let’s say if you hit / route on the browser the request in the laoder have cookies header where you can store the user’s authentication information. There you can write a custom login to check if the user is authenticated or not, and you can return that information.

    import { json, type LoaderFunctionArgs } from '@remix-run/node';
    import {
      useLoaderData,
    } from '@remix-run/react';
    import Home from 'some_path';
    import Login from 'some_path';
    
    export async function loader({ request }: LoaderFunctionArgs) {
      // extract the authentication information from request
      const isAuthenticated = {some_login}
      return json({
        isAuthenticated,
      });
    }
    

    Also, now you can access the loader data on client side.

    export default function Component() {
      const {isAuthenticated} = useLoaderData<typeof loader>()
    
      if (isAuthenticated) return <Home />
      return <Login />
    }
    

    The above code will be in your _index.ts file which will serve as your root route. Now if you are aware of Remix Routing: https://remix.run/docs/en/main/file-conventions/routes
    if you create another pages like /about or /stuff, all of them are by considered as children of _index.ts or / route. So if someone goes to /some_route the loader of the index page is called first and depending on the user authentication they will be routed.

    Lastly in the Home component simply import Outlet like this:

    import {
      Outlet,
    } from '@remix-run/react';
    
    export default function Home() {
      return <>
      -------------
        <Outlet/>
      -------------
      </>
    }
    

    The above Outlet will render the child pages

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search