16

I have an app which sometimes is loaded with a query string param t.

At the start, I want the app to read this param if available and remove it from the URL.

On the root component, I am doing this:

    const [searchParams, setSearchParams] = useSearchParams();

    if (searchParams.has('t')) {
        const token = searchParams.get('t');
        if (token) {
            searchParams.delete('t');
            const newParams: {[key: string]: string} = {};
            searchParams.forEach((value: string, key: string) => {
                newParams[key] = value;
            });
            console.log('setting params: ');
            console.dir(newParams);
            setSearchParams(newParams);
            AuthController.setAccessToken(token);
        }
    }

I see that it correctly reads param t and the newParams object is empty or contains only the other parameters, but for some reason setSearchParams(newParams) seems to not be doing anything. Parameter t is still in the URL.

How I can have it remove this parameter from the URL?

3
  • when you say setSearchParams(newParams) all you are doing is updating state of the component. That won't touch the URL itself. I've done some thing similar w/v5 but since you are using v6 I prefer not to add it as an answer. But for v5, I used useHistory & my code was history.push({pathname: <base route>, search: stringify(currentParams),}); And, const currentParams = parse(window.location.search.replace("?", "")); Commented Jan 13, 2022 at 15:30
  • Ahh, got it.. yeah I dont know whats the equivalent on v6, the documentation is not clear on this. Commented Jan 13, 2022 at 15:30
  • useNavigate I think, but haven't had the chance to work w/v6. Commented Jan 13, 2022 at 15:31

2 Answers 2

21

The setSearchParams updater function effectively is "navigate" but for only the queryString portion of the URL.

useSearchParams

Note:

The setSearchParams function works like navigate, but only for the search portion of the URL. Also note that the second arg to setSearchParams is the same type as the second arg to navigate.

You don't need to call navigate to update the queryString. The issue is doing this logic as an unintentional side-effect. Move all the logic into a useEffect hook and you'll find it works as you were expecting.

const [searchParams, setSearchParams] = useSearchParams();

useEffect(() => {
  if (searchParams.has("t")) {
    const token = searchParams.get("t");
    if (token) {
      searchParams.delete("t");
      console.log("setting params:", { searchParams: searchParams.toString() });
      console.dir(searchParams.toString());
      setSearchParams(searchParams);
    }
  }
}, []);

Edit why-does-react-router-v6-seem-unable-to-remove-query-string-param-from-url

Sign up to request clarification or add additional context in comments.

2 Comments

It might be relevant to people who come here to note that you don't actually need to use the searchParams you got from the hook in setSearchParams. You can also just pass a newly instantiated URLSearchParams object (or an array of pairs) if you want to replace all the parameters.
@PeterGerdes That is true, if you don't care to preserve any other existing queryString parameters you can just blow them away.
3

Got it to work!

This is what made the trick:

    const [searchParams, setSearchParams] = useSearchParams();
    const navigate = useNavigate();

    useEffect(() => {
        // remove the t parameter if it is present in the URL. This happens when we are redirected back from an OAuth
        // flow.
        if (searchParams.has('t')) {
            const token = searchParams.get('t');
            if (token) {
                searchParams.delete('t');
                const newParams: {[key: string]: string} = {};
                searchParams.forEach((value: string, key: string) => {
                    newParams[key] = value;
                });

                setSearchParams(newParams);
                navigate({
                    search: createSearchParams(newParams).toString(),
                }, {replace: true});

                AuthController.setAccessToken(token);
            }
        }

    }, [navigate, searchParams, setSearchParams]);

The code must be in useEffect and navigate must use the replace option. Now the param is removed.

1 Comment

In React Router 7, createSearchParams is not necessary. You can simply pass search: newParams.toString().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.