Skip to content

Using Navigate Instead of Redirect in React Router v6

Problem

When working with React Router, you may encounter the error:

Attempted import error: 'Redirect' is not exported from 'react-router-dom'

This error typically occurs when you're using React Router v6 but trying to import the Redirect component, which was removed in this major version update.

Solution

The Redirect component has been completely removed from React Router v6. Instead, you should use the Navigate component for declarative navigation or the useNavigate hook for programmatic navigation.

Using the Navigate Component

Replace any Redirect components with Navigate in your JSX:

jsx
import { Navigate } from 'react-router-dom';

// Instead of <Redirect to="/dashboard" />
<Navigate to="/dashboard" replace={true} />

Here's how to update your route configuration:

jsx
import { Switch, Redirect } from 'react-router-dom';

const Routes = () => {
  return (
    <Switch>
      <Redirect exact from="/" to="/dashboard" />
      {/* Other routes */}
      <Redirect to="/not-found" />
    </Switch>
  );
};
jsx
import { Routes, Route, Navigate } from 'react-router-dom';

const AppRoutes = () => {
  return (
    <Routes>
      <Route path="/" element={<Navigate to="/dashboard" replace />} />
      {/* Other routes */}
      <Route path="*" element={<Navigate to="/not-found" replace />} />
    </Routes>
  );
};

Using the useNavigate Hook

For programmatic navigation (e.g., after form submission or API calls), use the useNavigate hook:

jsx
import { useNavigate } from 'react-router-dom';

function LoginForm() {
  const navigate = useNavigate();
  
  const handleSubmit = async (e) => {
    e.preventDefault();
    // Perform login logic
    navigate('/dashboard', { replace: true });
  };
  
  return (
    <form onSubmit={handleSubmit}>
      {/* Form fields */}
    </form>
  );
}

WARNING

The Navigate component performs navigation in a useEffect, so it won't happen during the initial render. This is a intentional change in v6 to align with React's concurrent mode features.

Complete Migration Example

Here's a complete example of migrating from v5 to v6 routing patterns:

jsx
import { Switch, Redirect } from 'react-router-dom';
import { RouteWithLayout } from './components';

const Routes = () => {
  return (
    <Switch>
      <Redirect exact from="/" to="/dashboard" />
      <RouteWithLayout
        component={routeProps => <LoginView {...routeProps} />}
        exact
        layout={MinimalLayout}
        path="/login"
      />
      <Redirect to="/not-found" />
    </Switch>
  );
};
jsx
import { Routes, Route, Navigate } from 'react-router-dom';
import { RouteWithLayout } from './components';

const AppRoutes = () => {
  return (
    <Routes>
      <Route path="/" element={<Navigate to="/dashboard" replace />} />
      <Route
        path="/login"
        element={
          <RouteWithLayout layout={MinimalLayout}>
            <LoginView />
          </RouteWithLayout>
        }
      />
      <Route path="*" element={<Navigate to="/not-found" replace />} />
    </Routes>
  );
};

Alternative Approach: Downgrading

If you're not ready to migrate to v6 patterns, you can downgrade to React Router v5:

bash
npm install react-router-dom@5.3.4

or

bash
yarn add react-router-dom@5.3.4

DANGER

Downgrading is generally not recommended as you'll miss out on performance improvements, new features, and future support. The React Router team recommends migrating to v6 patterns.

Additional Considerations

  1. Route Pattern Changes: v6 uses different pattern matching logic. The exact prop is no longer needed as routes match exactly by default.

  2. Switch to Routes: The Switch component has been replaced with Routes in v6.

  3. Relative Links: v6 has improved support for relative links and navigation.

  4. Object-based Routes: v6 supports defining routes as JavaScript objects, which can be useful for programmatic route manipulation.

By migrating to the Navigate component and useNavigate hook, you'll be using the recommended patterns for React Router v6 and ensuring your application remains compatible with future updates.