Reputation: 6207
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
Reputation: 202979
The setSearchParams
updater function effectively is "navigate" but for only the queryString portion of the URL.
Note:
The
setSearchParams
function works likenavigate
, but only for the search portion of the URL. Also note that the second arg tosetSearchParams
is the same type as the second arg tonavigate
.
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);
}
}
}, []);
Upvotes: 21
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