Leo Messi
Leo Messi

Reputation: 6166

How to get the value from URL params in React

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

Answers (1)

Drew Reese
Drew Reese

Reputation: 202618

Issue

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.

Suggested Solution

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>
  );
}

Edit how-to-get-the-value-from-url-params-in-react

Upvotes: 1

Related Questions