Skip to content

DavidWells/next-with-react-router-v6

Repository files navigation

Next.js SPA with react router v6 deploy to netlify

Exports static routes for app and uses react router v6 for client side routing.

Inspired by this gist. Props to eddyw and tannerlinsley for the idea & code ❤️

How to use

Install deps

yarn

Run locally

yarn dev

Build

yarn build

Auth Methods

Here are various ways to have protected routes

Route switcher

Via bulletproof-react

import { useAuth } from '@/lib/auth';

const { ProtectedRoutes } = lazyImport(() => import('./ProtectedRoutes'), 'ProtectedRoutes');
const { PublicRoutes } = lazyImport(() => import('./PublicRoutes'), 'PublicRoutes');

export const AppRoutes = () => {
  const auth = useAuth();
  return auth.user ? <ProtectedRoutes /> : <PublicRoutes />;
};

/**
 * Defer loading of components & routes
 * named imports for React.lazy: https://github.com/facebook/react/issues/14603#issuecomment-726551598
 * @param factory - Component import resolver
 * @param name - Name of import key
 * @returns React component
 * @example
 * // Usage
 * const { Home } = lazyImport(() => import("./Home"), "Home");
 */
export function lazyImport<
  T extends React.ComponentType<any>,
  I extends { [K2 in K]: T },
  K extends keyof I
>(factory: () => Promise<I>, name: K): I {
  return Object.create({
    [name]: React.lazy(() => factory().then((module) => ({ default: module[name] }))),
  })
}

Private Routes

// ProtectedRoutes.js
import { Navigate, Outlet, Route, Routes } from 'react-router-dom';

import { MainLayout } from '@/components/Layout';
import { DiscussionsRoutes } from '@/features/discussions';
import { Landing, Dashboard } from '@/features/misc';
import { Profile, Users } from '@/features/users';

const App = () => {
  return (
    <MainLayout>
      <Outlet />
    </MainLayout>
  );
};

export const ProtectedRoutes = () => {
  return (
    <Routes>
      <Route path="/app" element={<App />}>
        <Route path="/discussions/*" element={<DiscussionsRoutes />} />
        <Route path="/users/*" element={<Users />} />
        <Route path="/profile" element={<Profile />} />
        <Route path="/" element={<Dashboard />} />
        <Route path="*" element={<Navigate to="/" />} />
      </Route>
      <Route path="/" element={<Landing />} />
    </Routes>
  );
};
// @/features/discussions DiscussionsRoutes
import { Route, Routes } from 'react-router-dom';

import { Discussion } from './Discussion';
import { Discussions } from './Discussions';

export const DiscussionsRoutes = () => {
  return (
    <Routes>
      <Route path="" element={<Discussions />} />
      <Route path=":discussionId" element={<Discussion />} />
    </Routes>
  );
};

Public Routes

// PublicRoutes.js
import { Navigate, Route, Routes } from 'react-router-dom';

import { AuthRoutes } from '@/features/auth';
import { Landing } from '@/features/misc';

export const PublicRoutes = () => {
  return (
    <Routes>
      <Route path="/auth/*" element={<AuthRoutes />} />
      <Route path="/" element={<Landing />} />
      <Route path="*" element={<Navigate to="/" />} />
    </Routes>
  );
};
// features/auth Routes
import { Route, Routes } from 'react-router-dom';

import { Login } from './Login';
import { Register } from './Register';

export const AuthRoutes = () => {
  return (
    <Routes>
      <Route path="register" element={<Register />} />
      <Route path="login" element={<Login />} />
    </Routes>
  );
};

Alternative approaches

About

Next.js with React Router v6 demo

Resources

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

No packages published