06 React/Next: 🔗 Routes, useParams, 🧭useNavigate, Outlet, useLocation()

06 React/Next: 🔗 Routes, useParams, 🧭useNavigate, Outlet, useLocation()

1. React Router Setup

npm i react-router-dom
or
npm install react-router-dom

2. React Router Configuration :

2.1 (a) "Navbar Component with Anchor Tags and React Router Links"

FileName: Navbar.js ⬇️

// abb: rfc
import React from 'react'

// react router dom ------------------
import { Link } from "react-router-dom";    // ⭐⭐⭐

export default function Navbar() {
    return (
        <>
            <div className='navbar'>
                <p>Anchor Tag : </p>
                <a href="/" >Home</a>
                <a href="/about" >About</a>
                <a href="/contact" >Contact</a>                
            </div>

            <div className='navbar'>
                <p>Link of React Router : </p>
                <Link to="/" >Home</Link>           // ⭐⭐⭐
                <Link to="/about" >About</Link>     // ⭐⭐⭐
                <Link to="/contact" >Contact</Link> // ⭐⭐⭐          
            </div>
        </>
    )
}
  • a is replaced by Link

  • href is replaced by to

2.1 (b) active nav Links

Reference Link : https://dev.to/gabrlcj/react-router-v6-some-of-the-new-changes-181m

✅ Correct way to 🖌️ apply dynamic classes 🎨

import { NavLink } from 'react-router-dom';

// Correct way to apply dynamic classes
<li>
  <NavLink
    to='/createUsername'
    className={(navData) =>
        `${navData.isActive ? 'active-link' : ''} navbar-link`
        // `${navData.isActive ? console.log(navData) : console.log(navData)} navbar-link`
    }
  >
    Create
  </NavLink>
</li>
.active-link {
    @apply underline text-amber-500;
}

2.2 "Rendering React Application with React Router Setup"

FileName: main.jsx ⬇️ (TOPMOST PARENT)

// FileName: main.jsx
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import { BrowserRouter } from 'react-router-dom'

ReactDOM.createRoot(document.getElementById('root')).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
)

2.3 "Setting Up Routes and Navbar in React Application (with BrowserRouter)"

// `FileName: App.js` ⬇️

// This is the correct way of React Router ✅✅✅
import Navbar from './Components/Navbar';

// react router --------------
import { BrowserRouter } from 'react-router-dom';   // ⭐⭐⭐

function App() {
  return (
    <>
      // <BrowserRouter>
        <Navbar />

        <Routes>
          <Route path='/home' element={<Home />} />
          <Route path='/about' element={<About />} />
          <Route path='/contact' element={<Contact />} />
        </Routes>

        <Footer />
      // </BrowserRouter>
    </>
  )
}

export default App;

3.useParams() - Hooks

How to use parameters in react

// File Name: Product.jsx
import React from 'react'
import { useParams } from 'react-router-dom' // ⭐⭐

const Product = ({value}) => {
    const params = useParams();

    return (
        <>
            <h2>Product ID: {params.id}</h2>
            <span>{value}</span> 
        </>
    )
}

export default Product

How to use navigate and props 👇

3.2 useParams and useNavigate Hooks

FileName: User.jsx

import React from 'react'

import { useParams, useNavigate } from 'react-router-dom' // ⭐⭐

export default function User({name="Regular User"}) {

    const params = useParams();
    console.log(params.id);

    const navigate = useNavigate();

    return (
        <div id='user-page' >
            User Page: {name}
            {/* <button type="button" onClick={()=>{ navigate("/about") }} >Click Me to Navigate </button> */}

        </div>
    )
}

3.3 React Router Configuration with Dynamic Routes and Navigation

// File Name: App.js
import './App.css';
// Importing Components files
import Navbar from './components/Navbar';
import Home from './components/Home';
import Contact from './components/Contact';
import About from './components/About';
import User from './components/User';
import Footer from './components/Footer';

// 1. react router --------------
import { BrowserRouter } from 'react-router-dom';
// 2. react router --------------
import { Route, Routes } from 'react-router-dom';
import Product from './components/Product';

function App() {
  return (
    <>
      {/* 2. ------------------------ */}
      <BrowserRouter>
        <Navbar />

        {/* jo pehle match ho gya wo render ho jaayega */}
        <Routes>
          <Route path="/user/admin" element={<User name="Admin" />} />
          {/* http://localhost:3000/user/abc    🎯 if any query is there in place of ':id' then below Route is rendered */}
          <Route path="/user/:id" element={<User />} />   
          <Route path="/user" element={<User />} />

          <Route path='/product/:id' element={<Product />} />


        {/* 🅾️ Outlet component is used to render child routes within a parent route. */}
        <Route path='/display/' element={<UsernameForm />} >
          <Route path='/display/:username' element={<ShowUsername />} />
        </Route>

        {/* Catch-all route for undefined paths - WILDCARD ROUTE (keep always at end) */}
        <Route path="*" element={<h1>Page 404 Not Found !</h1>} />

        </Routes>

        <Footer />
      </BrowserRouter>

    </>
  )
}

export default App;

Use Outlet 🪈 in any component :

import { Outlet } from 'react-router-dom';

const UsernameForm = () => {
    return (
        <>
            <div className="max-w-md mx-auto p-4 bg-white shadow-md rounded-lg">
            </div>

            <Outlet />
        </>
    );
};
export default UsernameForm;

useLocation() :

// FileName: /components/nav.jsx
import { useLocation } from 'react-router-dom';

const Nav = () => {
    const location = useLocation();
    console.log(location);
    return (
       <></>
    )
}

export default Nav

useRef() :

  • Used for accessing and interacting with DOM elements directly or storing mutable values that don’t require a re-render.
import { useRef, useState } from 'react';

const UsernameForm = () => {
    const [username, setUsername] = useState('');
    const { users, setUsers } = useContext(UserContext);

    const [isError, setIsError] = useState(false); // // ⭐⭐⭐
    const myInpRef = useRef(null);    // ⭐⭐⭐

    const handleChangeInput = (e) => {
        // console.log(myInpRef);
        // console.log(myInpRef.current);
        // console.log(myInpRef.current.value);
        if (myInpRef.current.value.length > 4) {
            setIsError(false);
        } else {
            setIsError(true);
        }
        setUsername(e.target.value);
    }

    return (
        <>
            <label htmlFor="username" className="block text-sm font-medium text-gray-700">Username</label>
            <input
                ref={myInpRef}    // ⭐⭐⭐                            
                type="text"
                id="username"
                value={username}
                onChange={handleChangeInput} // ⭐⭐⭐
                /* 🚫 onChange={(e) => setUsername(e.target.value)} */
                className="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
                required
            />
             { // ⭐⭐⭐
               isError && ( <small className='my-error'>Invalid User Name</small> )
             }
        </>
    );
};

export default UsernameForm;

NEXT JS ROUTES:

Next.js provides a simple and intuitive routing system that allows you to define routes for your application's pages.