Reputation: 6166
Having the following component:
import { ChangeEvent, useCallback, useState } from 'react';
export function SearchComponent() {
const [searchValue, setSearchValue] = useState<string>('');
const updateSearchValue = useCallback((event: ChangeEvent<HTMLInputElement>) => {
setSearchValue(event.target.value);
}, []);
return (
<div>
<input value={searchValue} onChange={updateSearchValue} />
</div>
);
}
It updates that state value, searchValue
with the value introduced in the input.
With that value, the URL is updated like this:
window.location.hash = searchValue ? `?searchBy=${searchValue}` : '';
It add an extra #
to the URL, before it was example.com/test
, now it is example.com/test#?searchBy=my_input
but it's not a big issue.
What I want is to be able modify directly the input and store that new value in the component, so I've tried like this:
const queryParams = new URLSearchParams(window.location.search);
const searchBy = queryParams.get('searchBy');
When logged, queryParams
is an empty object while searchBy
is null
.
Is there a way to store the value from the URL if the user is going to edit that value?
Upvotes: 1
Views: 1327
Reputation: 202618
The issue is that window.location.hash = searchValue ? `?searchBy=${searchValue}` : '';
updates the location hash, thus adding the "#"
to the URL, and not the window.location.search
, which is the queryString part of the URL.
Using window.location
is also a bit of an anti-pattern as it mutates the location and forces a reload of the page. Better to use the tools available to you from react-router-dom
to issue a navigation action instead of reloading the entire app.
Using react-router-dom@5
you will need to use the useHistory and useLocation hooks and access the location.search
value and instantiate your own URLSearchParams object. Set the initial searchValue
state from the queryString, and use a useEffect
hook to update the search params and issue an imperative redirect to the current route with the updated queryString.
Example:
import { useLocation, useHistory } from 'react-router-dom';
export function SearchComponent() {
const history = useHistory();
const { pathname, search } = useLocation();
const searchParams = React.useMemo(() => new URLSearchParams(search), [
search
]);
const [searchValue, setSearchValue] = useState<string>(
searchParams.get("searchBy") || ""
);
useEffect(() => {
searchParams.set("searchBy", searchValue);
history.replace({
pathname,
search: searchParams.toString(),
});
}, [history, pathname, searchParams, searchValue]);
const updateSearchValue = useCallback((event: ChangeEvent<HTMLInputElement>) => {
setSearchValue(event.target.value);
}, []);
return (
<div>
<input value={searchValue} onChange={updateSearchValue} />
</div>
);
}
Upvotes: 1