My React project passes data from a component to FoodDetails and this works, but I want it to navigate away if the state property of location from the useLocation is null.
Code:
const FoodDetails = () => {
const navigate = useNavigate();
const location = useLocation();
if (location.state === null) {
navigate("/")
}
const food = location.state.food;
return (
<div className='FoodDetails'>
<div className="FoodDetailsName">{food.name}</div>
</div>
)
}
export default FoodDetails
It goes into the if, but it ignores the navigate("/"). I've placed a return after it and the return works so it just overlooks the navigate.
Why does it ignore it and how can I fix it?
CodePudding user response:
You need to place navigate("/") inside useEffect. Something like:
const FoodDetails = () => {
const navigate = useNavigate();
const location = useLocation();
const locationState = location.state;
useEffect(() => {
if(locationState === null){
navigate("/");
}
}, [locationState]);
const food = location.state.food;
return (
<div className='FoodDetails'>
<div className="FoodDetailsName">{food.name}</div>
</div>
);
}
export default FoodDetails;
useEffect's callback will be run every time something inside its dependency array changes. In this case locationState. Note that it's good idea to deconstruct dependencies before useEffect.
CodePudding user response:
The navigate function issues an imperative navigation action, and the current implementation is calling as an unintentional side-effect. While you could use a useEffect hook to call navigate as an intentional side-effect, the component still renders first and then the useEffect hook callback is called. You'd see the returned JSX momentarily.
I would suggest conditionally rendering the Navigate component instead. It will issue a declarative navigation action during the initial render cycle. The other food details JSX won't have a chance to be rendered.
In either case though the FoodDetails component and route/page will be loaded/rendered. This is just a way to mitigate rendering momentary UI that you don't want a user to see.
Example:
import { Navigate } from 'react-router-dom';
const FoodDetails = () => {
const { state } = useLocation();
const { food } = state || {};
if (!food) {
return <Navigate to="/" />;
}
return (
<div className='FoodDetails'>
<div className="FoodDetailsName">{food.name}</div>
</div>
);
};
export default FoodDetails;
