DEV Community

ugurgunes95
ugurgunes95

Posted on

React JS Conditional Routing Logic Implementation

React JS Conditional Routing Logic Implementation

Setup

  • First things first we need to create our basic react application. In order to do that, open a terminal in a preferred location on your pc and run this command: npm create vite@latest.

Note that; in this example I have used vite. But you can also use create-react-app etc.

  • After the command above it will ask you for a project name, framework and variant. I am going to use TypeScript React template.

  • When you've created the project run this command to all the install dependencies and react-router;

  npm install && npm install react-router-dom@latest
Enter fullscreen mode Exit fullscreen mode

or if you're using yarn;

  yarn install && yarn add react-router-dom@latest
Enter fullscreen mode Exit fullscreen mode
  • Now I am going to delete unnecessary files etc. At the end of the setup section your file tree will look like this:
  ugur@gunes:~/Development/reactjs/test$ tree --dirsfirst
  .
  ├── public
  ├── src
  │   ├── index.css
  │   ├── Layout.tsx
  │   ├── main.tsx
  │   └── vite-env.d.ts
  ├── index.html
  ├── package.json
  ├── tsconfig.json
  ├── tsconfig.node.json
  └── vite.config.ts

  3 directories, 9 files
Enter fullscreen mode Exit fullscreen mode
  • That's it for our basic setup.

Configuration

So let's create our pages which we're going to use in the next steps.

Creating Pages

  • I'll create a directory named pages in src folder. And inside of that directory I'll also create two other directories just to make the situation more clear.
  • I am creating AuthorizedPages and UnauthorizedPages directories in the src/pages folder.
  • And I will just create two components; one for AuthorizedPages(Home.tsx) and one for UnauthorizedPages(Login.tsx).

-

  // Home.tsx

  import { useContext } from "react";
  import { AuthContext } from "../../context/AuthContext.tsx";

  const Home = () => {
    const { setLoginContext } = useContext(AuthContext);
    return (
      <section>
        <h1>Home Page</h1>
        <button onClick={() => setLoginContext(false)}>Logout</button>
      </section>
    );
  };

  export default Home;
Enter fullscreen mode Exit fullscreen mode

-

  // Login.tsx

  import { useContext } from "react";
  import { AuthContext } from "../../context/AuthContext.tsx";

  const Login = () => {
    const { setLoginContext } = useContext(AuthContext);
    return (
      <section>
        <h1>Login Page</h1>
        <button onClick={() => setLoginContext(true)}>Login</button>
      </section>
    );
  };

  export default Login;
Enter fullscreen mode Exit fullscreen mode
  • Here's how it looks at the end:
  .
  ├── public
  ├── src
  │   ├── pages
  │   │   ├── AuthorizedPages
  │   │   │   └── Home.tsx
  │   │   └── UnauthorizedPages
  │   │       └── Login.tsx
  │   ├── index.css
  │   ├── Layout.tsx
  │   ├── main.tsx
  │   └── vite-env.d.ts
  ├── index.html
  ├── package.json
  ├── tsconfig.json
  ├── tsconfig.node.json
  └── vite.config.ts

  6 directories, 11 files
Enter fullscreen mode Exit fullscreen mode
  • Check the page files' content on the github repository.

Creating AuthContext

In this section we'll create AuthContext. I will not implement authentication logic to make this article short and less complicated. Instead we'll just simulate it.

  • I am creating a directory called context under our src folder.
  • In this directory we'll create 4 files: AuthContext.tsx, AuthContextType.tsx, AuthContextProviderPropType.tsx and AuthContextInitialState.tsx.
  • Creating 4 different files is not necessary but I just like to seperate them.
  • File's contents will be like that:
  // AuthContext.tsx

  import { createContext, useState } from "react";
  import { AuthContextType } from "./AuthContextType.tsx";
  import { AuthContextInitialState } from "./AuthContextInitialState.tsx";
  import { AuthContextProviderPropType } from "./AuthContextProviderPropType.tsx";

  export const AuthContext = createContext<AuthContextType>(
  AuthContextInitialState,
  );

  export const AuthContextProvider = ({
  children,
  }: AuthContextProviderPropType) => {
  const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false);
  const [loading, setLoading] = useState<boolean>(false);
  const setLoginContext = (status: boolean = false) => {
      // simulate login logic
      setLoading(true);
      setTimeout(() => {
      setIsLoggedIn(status);
      setLoading(false);
      }, 1500);
  };
  return (
      <AuthContext.Provider value={{ loading, isLoggedIn, setLoginContext }}>
      {children}
      </AuthContext.Provider>
  );
  };
Enter fullscreen mode Exit fullscreen mode
  // AuthContextType.tsx

  export interface AuthContextType {
    loading: boolean;
    isLoggedIn: boolean;
    setLoginContext: (status: boolean) => void;
  }
Enter fullscreen mode Exit fullscreen mode
  // AuthContextProviderPropType.tsx
  import React from "react";

  export interface AuthContextProviderPropType {
    children: React.ReactNode;
  }
Enter fullscreen mode Exit fullscreen mode
  // AuthContextInitialState.tsx
  import { AuthContextType } from "./AuthContextType.tsx";

  export const AuthContextInitialState: AuthContextType = {
    loading: false,
    isLoggedIn: false,
    setLoginContext: () => {},
  };
Enter fullscreen mode Exit fullscreen mode
  • The end of context setup... it's pretty straight forward stuff.

Creating Routing Files

Now it's time to create routing part. As I said before I like to keep files seperately. Let's create our routing files. In order to do that I'll create 1 directory and 3 files in it.

  • Create routing directory under the src folder.
  • In the routing folder create 3 files and name them as you wish. I'll name them; AuthorizedRoutes.tsx, UnAuthorizedRoutes.tsx and BaseRouting.tsx.
  • Let's now create the content for theses files:
  // AuthorizedRoutes.tsx
  import { RouteObject } from "react-router-dom";
  import Home from "../pages/authorized-pages/Home.tsx";

  const AuthorizedRoutes: RouteObject[] = [
    {
      path: "",
      element: <Home />,
    },
    {
      path: "home",
      element: <Home />,
    },
  ];

  export default AuthorizedRoutes;
Enter fullscreen mode Exit fullscreen mode
  // UnAuthorizedRoutes.tsx
  import { RouteObject } from "react-router-dom";
  import Login from "../pages/unauthorized-pages/Login.tsx";

  const UnAuthorizedRoutes: RouteObject[] = [
    {
      path: "",
      element: <Login />,
    },
    {
      path: "login",
      element: <Login />,
    },
  ];

  export default UnAuthorizedRoutes;
Enter fullscreen mode Exit fullscreen mode
  // BaseRouting.tsx
  import { createBrowserRouter, RouterProvider } from "react-router-dom";
  import Layout from "../components/Layout.tsx";
  import { useContext } from "react";
  import { AuthContext } from "../context/AuthContext.tsx";
  import AuthorizedRoutes from "./AuthorizedRoutes.tsx";
  import UnAuthorizedRoutes from "./UnAuthorizedRoutes.tsx";
  import ErrorComponent from "../components/ErrorComponent.tsx";

  const RoutingProvider = () => {
    const { isLoggedIn } = useContext(AuthContext);
    const router = createBrowserRouter([
      {
        path: "/",
        element: <Layout />,
        errorElement: <ErrorComponent />,
        children: isLoggedIn ? [...AuthorizedRoutes] : [...UnAuthorizedRoutes],
      },
    ]);

    return <RouterProvider router={router} />;
  };

  export default RoutingProvider;
Enter fullscreen mode Exit fullscreen mode
  • What we did? Let's review...
  • BaseRouting.tsx file is our main routing file. Inside of that we have our Layout component which is like wrapper for our app.
  • But the children of our main route is depends to the isLoggedIn state which we've created in out context part.
  • If there is a logged in user; we'll render the app with routes requires authorization, if there isn't we'll render the app with unauthorized routes.

  • This way we're also make Login route not accessible if user is logged in.

Configure Our Main.ts File

  • We need to apply those to our app:
  // main.tsx
  import ReactDOM from "react-dom/client";
  import "./index.css";
  import { AuthContextProvider } from "./context/AuthContext.tsx";
  import RoutingProvider from "./routing/BaseRouting.tsx";

  ReactDOM.createRoot(document.getElementById("root")!).render(
    <AuthContextProvider>
      <RoutingProvider />
    </AuthContextProvider>,
  );

Enter fullscreen mode Exit fullscreen mode

Conclusion

That's it. I am not exactly sure if this approach is convenient, but I am pretty sure that I'll use it in my next projects. Hope it helps you people.

Github Repo

Top comments (0)