I want to validate the params in my component and do a redirect if they don't pass some logic.
Two things can go wrong:
Warning: Cannot update a component (`BrowserRouter`) while rendering a different component (`Home`).
You should call navigate() in a React.useEffect(), not when your component is first rendered.
I'm not sure I understand why I can't return null, or return any random element from the logic and still have it redirect properly.
I understand it works with useEffect, but I actually want to end execution of the rendering of my component early, to prevent logic further down in the component from running, in the case that the params aren't properly formatted.
See the codesandbox here, (you have to change the url to add an id number): https://codesandbox.io/s/nostalgic-cloud-di0ovf
import "./styles.css";
import {
BrowserRouter,
Routes,
Route,
Link,
useNavigate,
useParams,
} from "react-router-dom";
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/:id" element={<Home />} />
<Route path="/users" element={<Users />} />
</Routes>
</BrowserRouter>
);
}
function Users() {
return (
<div>
<nav>
<Link to="/1">Go To 1 (bad param)</Link>
</nav>
<h2>Users</h2>
</div>
);
}
function Home() {
const navigate = useNavigate();
const {id} = useParams();
// check for properly formed params
if( id < 3){
navigate({pathname:'/users', replace:true})
return <span>nothing</span>;
}
// other logic that depends on properly formed params
// don't run this with mal-formed params!
return (
<div>
<nav>
<Link to="/1">Go To 1 (bad param)</Link>
</nav>
<h1>Home: {id}</h1>
</div>
);
}
You should split the logic of issuing the intentional side-effect of navigating from the logic of rendering valid JSX.
Example:
function Home() {
const navigate = useNavigate();
const { id } = useParams();
useEffect(() => {
if (id < 3) {
navigate('/users', { replace: true });
}
}, [id, navigate]);
// check for properly formed params
if (id < 3) {
return <span>nothing</span>; // or null
}
// other logic that depends on properly formed params
// don't run this with mal-formed params!
return (
<div>
<nav>
<Link to="/1">Go To 1 (bad param)</Link>
</nav>
<h1>Home: {id}</h1>
</div>
);
}
Alternatively you can render a declarative redirect instead.
Example:
function Home() {
const { id } = useParams();
// check for properly formed params
if (id < 3) {
return <Navigate to='/users' replace />;
}
// other logic that depends on properly formed params
// don't run this with mal-formed params!
return (
<div>
<nav>
<Link to="/1">Go To 1 (bad param)</Link>
</nav>
<h1>Home: {id}</h1>
</div>
);
}