How to update location.state in react-router v6?
Asked Answered
K

4

8

I'm using react-router-dom v6. When using useNavigate like this:

let navigate = useNavigate();
navigate("/", {state: state});

I can access it by useLocation().location.state

My question is how to remove this state after i don't need it, for example in useEffect cleanup function.

Kidding answered 5/5, 2022 at 2:21 Comment(0)
K
14

My question is how to remove this state after I don't need it

You could read the passed route state into local component state and issue a redirect without state to the current path to clear out the state. This would prevent any back navigations to the page to retain any route state.

Example:

const Component = () => {
  const location = useLocation();
  const navigate = useNavigate();

  const [state] = useState(location.state || {}); // <-- cache state locally

  useEffect(() => {
    navigate(".", { replace: true }); // <-- redirect to current path w/o state
  }, [navigate]);

  return ( ... );
};

Edit how-to-update-location-state-in-react-router-v6

Kramlich answered 5/5, 2022 at 3:1 Comment(7)
I've been using null instead of any specific path like "." which behaves the same way. navigate(null, { replace: true, state: { updatedStateGoesHere } })Gregggreggory
@Gregggreggory using null doesn't work in typescriptSurprint
That's right, the navigate function's declaration requires a to argument that is of type To, which is string | Partial<Path>. Passing null isn't valid.Kramlich
that's odd. I am using Typescript without issue. Out of curiosity, does undefined work better for you guys?Gregggreggory
You can simply pass in an empty object: navigate({}, { replace: true }); Delores
@Delores That may work because the Partial<Path> doesn't require any of pathname, search, or hash, but I'd say it'd be better to be more explicit with the object, e.g. navigate({ pathname: "." }, { replace: true });.Kramlich
@Gregggreggory you might not have strict null checks turned on?Mcmann
A
0

You should import useNavigate from react-router-dom:

import { useNavigate } from 'react-router-dom';

then make a variable:

const navigate = useNavigate();

then:

<button onClick={() => navigate('/')}><button>

And you are done.

Adoration answered 5/5, 2022 at 2:26 Comment(0)
M
0

I noticed the other answers cause the querystring to disappear, because they pass strings as navigates the first param. If you want to keep everything in the URL and just change the state, you can pass location as the first param.

const Component = () => {
  const location = useLocation();
  const navigate = useNavigate();

  ...

  useEffect(() => {
    if (shouldClearState) {
        // the options object does not have state defined, so it gets cleared
        navigate(location, { replace: true });
    }
  }, [location, navigate]);

  return ( ... );
};

This works because it matches the To interface, which takes the pathname, search, and hash. Note that state is not read off the first param, because it doesn't exist on To.

Mcmann answered 20/8, 2024 at 14:45 Comment(0)
T
-1

If you need to update the state, consider to use History APIs:

interface History {
    ...
    pushState(data: any, unused: string, url?: string | URL | null): void;
    replaceState(data: any, unused: string, url?: string | URL | null): void;
}

The entire history instance culd be reached via window.history. So, the answer to your question will be:

window.history.replaceState({}, 'my page');

I hope it will help to someone.

Tepic answered 21/5, 2024 at 4:32 Comment(1)
If you're using ReactRouter, it's not recommended to interact with History directlyMcmann

© 2022 - 2025 — McMap. All rights reserved.