Routing With JSX

When building React applications, routing is like the GPS for your app: it tells users how to navigate and where to go within your interface. In React, one of the most popular ways to manage this navigation is by using React Router.

Understanding JSX Routing

JSX is a syntax extension for JavaScript that looks like HTML, but under the hood, it's just a special way of writing JavaScript function calls. React Router provides two ways to define routes:

Both approaches lead to the same outcome but have slightly different setups. For developers working with older React Router code bases or following certain examples from the official docs, the JSX approach can be more familiar.

Why This Matters

Think of React Router as a well-trained guide dog who helps your user journey from page to page. Using JSX to define routes is especially handy when:

Project Structure Example

Below is an example folder structure you might see in a simple React project using JSX for routing. Notice that the filenames have no spaces or hyphens:


my_react_app/
  package.json
  src/
    index.js
    App.jsx
    Home.jsx
    TeamsIndex.jsx
    TeamDetails.jsx
    router.jsx
    ...
  public/
    index.html
  ...
  

In this structure:

Declaring Routes Using JSX

Let's say we have a single route object that maps the path / to a Home component:


// Route object version
{
  path: '/',
  element: <Home />
}
  

To achieve the same result using JSX, we write:


<Route path='/' element={<Home />} />
  

This Route component is imported from react-router-dom. It takes two key props:

Nested Routes With JSX

In real life, routes often branch off into smaller sub-routes. Imagine your app is a big house; each room could be a route, and some rooms have closets or smaller compartments (nested routes). In JSX, you wrap the Route for the parent around its child routes, instead of using an array of children:


<Route path='teams'>
  <Route index={true} element={<TeamsIndex />} />
  <Route path=':teamId' element={<TeamDetails />} />
</Route>
  

This tells React Router:

Converting JSX Routes Using createRoutesFromElements

So how do we transform our JSX into an array of route objects that createBrowserRouter expects? The answer is createRoutesFromElements. It’s like a professional translator that takes your JSX syntax and converts it into a format the router can digest.


import { 
  createBrowserRouter, 
  RouterProvider, 
  Route, 
  createRoutesFromElements 
} from 'react-router-dom';

const router = createBrowserRouter(
  createRoutesFromElements(
    <>
      <Route path='/' element={<h1>Home Component</h1>} />
      <Route path='teams'>
        <Route index element={<h1>Teams Index Component</h1>} />
        <Route path=':teamId' element={<h1>Team Details Component</h1>} />
      </Route>
    </>
  )
);

function App() {
  return <RouterProvider router={router} />;
}

export default App;
  

<></> is a React Fragment. We use it to group multiple Route elements without adding extra markup.

Step By Step Example

Imagine you want to build an app where the homepage is just "Welcome Home!", and you have a teams page showing either the "Teams Index" or details for a specific team.

Let’s walk through how you might set that up. (Feel free to follow along in your own project or create a fresh React app using create-react-app, Vite, or any setup you prefer.)

Placing the Files

In src/:

  1. Home.jsx:
    
    import React from 'react';
    
    function Home() {
      return <h2>Welcome Home!</h2>;
    }
    
    export default Home;
          
  2. TeamsIndex.jsx:
    
    import React from 'react';
    
    function TeamsIndex() {
      return <h2>Here are the teams!</h2>;
    }
    
    export default TeamsIndex;
          
  3. TeamDetails.jsx:
    
    import React from 'react';
    import { useParams } from 'react-router-dom';
    
    function TeamDetails() {
      const { teamId } = useParams();
      return <h2>Details for Team: {teamId}</h2>;
    }
    
    export default TeamDetails;
          
  4. router.jsx:
    
    import React from 'react';
    import { 
      createBrowserRouter, 
      createRoutesFromElements, 
      Route 
    } from 'react-router-dom';
    
    import Home from './Home';
    import TeamsIndex from './TeamsIndex';
    import TeamDetails from './TeamDetails';
    
    const router = createBrowserRouter(
      createRoutesFromElements(
        <>
          <Route path='/' element={<Home />} />
    
          <Route path='teams'>
            <Route index element={<TeamsIndex />} />
            <Route path=':teamId' element={<TeamDetails />} />
          </Route>
        </>
      )
    );
    
    export default router;
          
  5. App.jsx:
    
    import React from 'react';
    import { RouterProvider } from 'react-router-dom';
    import router from './router';
    
    function App() {
      return <RouterProvider router={router} />;
    }
    
    export default App;
          

Now, when you run your app, visiting http://localhost:3000/ (or your local development port) should show Welcome Home!. Visiting http://localhost:3000/teams shows the "Here are the teams!" page. Going to http://localhost:3000/teams/76ers will render "Details for Team: 76ers" and so on.

Analogies and Real World Usage

Think of your app as a city and each route as a distinct neighborhood. Using JSX to declare routes is like giving each neighborhood a signpost that says "Head this way for the Home area" or "Enter here for the Teams area."

Wherever users need to switch views based on specific URLs, React Router helps keep the journey smooth and intuitive.

Exercise: Try It Yourself

Practice solidifies knowledge! Here’s a quick exercise:

Extra Topics to Explore

Conclusion

You've seen how to declare routes using JSX and how to use createRoutesFromElements to translate them into objects that createBrowserRouter understands. This approach is valuable for its readability, especially in codebases that prefer a more explicit, "JSX-first" style for everything related to UI.

Happy Routing!