A component-based version of useNavigate to use in a React Component class where hooks cannot be used.
It’s recommended to avoid using this component in favor of useNavigate.
import { Navigate } from "react-router";
class MyComponent extends React.Component {
render() {
return this.state.shouldRedirect ? (
<Navigate to="/dashboard" />
) : (
<div>Content</div>
);
}
}
Type Declaration
export interface NavigateProps {
to: To;
replace?: boolean;
state?: any;
relative?: RelativeRoutingType;
}
export function Navigate({
to,
replace,
state,
relative,
}: NavigateProps): null;
type To = string | Partial<Path>;
type RelativeRoutingType = "route" | "path";
Props
The path to navigate to. Can be a string or a Path object.<Navigate to="/dashboard" />
<Navigate
to={{
pathname: "/search",
search: "?q=react",
hash: "#results",
}}
/>
Whether to replace the current entry in the History stack instead of pushing a new one.<Navigate to="/dashboard" replace />
State to pass to the new Location to store in history.state.<Navigate to="/dashboard" state={{ from: "login" }} />
How to interpret relative routing in the to prop.
- route (default) - Relative to the route hierarchy
- path - Relative to the URL path
<Navigate to=".." relative="route" />
<Navigate to=".." relative="path" />
Examples
Basic Redirect
function ProtectedRoute({ children }) {
const user = useUser();
if (!user) {
return <Navigate to="/login" />;
}
return children;
}
With Replace
function OldPage() {
// Don't let users go back to this page
return <Navigate to="/new-page" replace />;
}
Conditional Navigation
function Checkout() {
const cart = useCart();
if (cart.items.length === 0) {
return <Navigate to="/cart" />;
}
return (
<div>
<h1>Checkout</h1>
{/* checkout form */}
</div>
);
}
With State
function LoginRequired({ children }) {
const user = useUser();
const location = useLocation();
if (!user) {
return (
<Navigate
to="/login"
state={{ from: location.pathname }}
replace
/>
);
}
return children;
}
// In Login component
function Login() {
const location = useLocation();
const navigate = useNavigate();
const from = location.state?.from || "/";
async function handleSubmit(event) {
event.preventDefault();
await login();
navigate(from, { replace: true });
}
return <form onSubmit={handleSubmit}>{/* ... */}</form>;
}
In Class Components
class OldClassComponent extends React.Component {
render() {
if (this.state.redirect) {
return <Navigate to="/dashboard" />;
}
return (
<div>
<button onClick={() => this.setState({ redirect: true })}>
Go to Dashboard
</button>
</div>
);
}
}
Index Route Redirect
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Navigate to="dashboard" replace />} />
<Route path="dashboard" element={<Dashboard />} />
<Route path="settings" element={<Settings />} />
</Route>
</Routes>
Behavior
- Navigates immediately when rendered
- The navigation happens in a
useEffect to avoid render-time side effects
- Cannot be used on the initial render in a
<StaticRouter> (server-side rendering)
- Returns
null - does not render any DOM elements
Warnings
<Navigate> must not be used on the initial render in a <StaticRouter>. This is a no-op, but you should modify your code so the <Navigate> is only ever rendered in response to some user interaction or state change.
Alternative
In most cases, you should use the useNavigate hook instead:
function MyComponent() {
const navigate = useNavigate();
const user = useUser();
useEffect(() => {
if (!user) {
navigate("/login");
}
}, [user, navigate]);
return <div>Content</div>;
}
Or use a loader to protect routes:
// Route configuration
{
path: "dashboard",
loader: protectedLoader,
Component: Dashboard,
}
// Loader
async function protectedLoader() {
const user = await getUser();
if (!user) {
throw redirect("/login");
}
return null;
}