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
or if you're using yarn;
yarn install && yarn add react-router-dom@latest
- 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
- 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
insrc
folder. And inside of that directory I'll also create two other directories just to make the situation more clear. - I am creating
AuthorizedPages
andUnauthorizedPages
directories in thesrc/pages
folder. - And I will just create two components; one for
AuthorizedPages(Home.tsx)
and one forUnauthorizedPages(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;
-
// 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;
- 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
- 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 oursrc
folder. - In this directory we'll create 4 files:
AuthContext.tsx
,AuthContextType.tsx
,AuthContextProviderPropType.tsx
andAuthContextInitialState.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>
);
};
// AuthContextType.tsx
export interface AuthContextType {
loading: boolean;
isLoggedIn: boolean;
setLoginContext: (status: boolean) => void;
}
// AuthContextProviderPropType.tsx
import React from "react";
export interface AuthContextProviderPropType {
children: React.ReactNode;
}
// AuthContextInitialState.tsx
import { AuthContextType } from "./AuthContextType.tsx";
export const AuthContextInitialState: AuthContextType = {
loading: false,
isLoggedIn: false,
setLoginContext: () => {},
};
- 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 thesrc
folder. - In the
routing
folder create 3 files and name them as you wish. I'll name them;AuthorizedRoutes.tsx
,UnAuthorizedRoutes.tsx
andBaseRouting.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;
// 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;
// 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;
- What we did? Let's review...
-
BaseRouting.tsx
file is our main routing file. Inside of that we have ourLayout
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>,
);
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.
Top comments (0)