I have a problem with navigation between two routes of same component.
I have a page where there is a form to create and edit user. The routes are:
/user
/user/:id
But when try navigate from /user/:id to /user to create new user, the states of component not redeclared. The states come with the same value of page /user/:id. This is occur only when navigate to same component.
See routes:
<Route path='user/:id' element={<UserForm />} />
<Route path='user' element={<UserForm />} />
The component:
const UserForm = () => {
const navigate = useNavigate();
const params = useParams<FormParams>();
// const [searchParams, setSearchParams] = useSearchParams();
const [loading, setLoading] = useState<boolean>(true);
const [message, setMessage] = useState<MessageProps>();
const [data, setData] = useState<UserModel>(newData);
...
}
export default UserForm;
Redirect Function:
const newForm = () => {
try {
debugger;
navigate('/user');
} catch (error) {
console.log("ERROR");
}
}
If I refresh page, the states is redeclared. As it should happen in the redirect.
CodePudding user response:
react-router-dom
is optimized to not unnecessarily unmount and remount components.
<Route path='user/:id' element={<UserForm />} />
<Route path='user' element={<UserForm />} />
When switching between "/user"
and "/user/:id"
the UserForm
component will only get rerendered. The same is true if you navigate from one "/user/:id"
path to a different "/user/:id"
path. It's clear that UserForm
has a dependency on this id
route path parameter. You've a couple options for handling this.
Use a
useEffect
hook with a dependency on theid
route param and rerun/reset any state.const UserForm = () => { const navigate = useNavigate(); const { id } = useParams<FormParams>(); // const [searchParams, setSearchParams] = useSearchParams(); const [loading, setLoading] = useState<boolean>(true); const [message, setMessage] = useState<MessageProps>(); const [data, setData] = useState<UserModel>(newData); useEffect(() => { // reset state or re-issue side-effect based on id param }, [id]); ... }
Add a React key to the
UserForm
component in the route so React will unmount/mount a new instance when switching between"/user"
and"/user/:id"
. Note however that you'd still need auseEffect
hook to rerun/reset logic/state when staying on the same route and only theid
changes.<Route path='user/:id' element={<UserForm key="root" />} /> <Route path='user' element={<UserForm key="id" />} />