Home > Mobile >  I have a problem with React Router Dom V6 and useState
I have a problem with React Router Dom V6 and useState

Time:08-07

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.

  1. Use a useEffect hook with a dependency on the id 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]);
      ...
    }
    
  2. 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 a useEffect hook to rerun/reset logic/state when staying on the same route and only the id changes.

    <Route path='user/:id' element={<UserForm key="root" />} />
    <Route path='user' element={<UserForm key="id" />} />
    
  • Related