Edy Bourne
Edy Bourne

Reputation: 6207

Why does React Router v6 seem unable to remove query string param from URL?

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?

Upvotes: 16

Views: 34557

Answers (2)

Drew Reese
Drew Reese

Reputation: 202979

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

Upvotes: 21

Edy Bourne
Edy Bourne

Reputation: 6207

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.

Upvotes: 3

Related Questions