Working with a query string in React

Hey. This is the article about the package that I missed in working with react.



image



To be more specific, about a package for improving and facilitating work with queries from the search bar.



How do you do it now



Retrieving values



How do you get the value from the query string? I think something like this:



const { item } = queryString.parse(props.location.search);


or if you are familiar with URLSearchParams, you can do it like this:



const params = new URLSearchParams(props.location.search);
const item = params.get('item');


Which option is more preferable is not entirely clear, since the first pulls up the npm package, but works everywhere, and the second is built into the browser, but there may be problems with IE ( mozilla ).



Setting values



We figured out the receipt, somehow, but still got exactly the same result as we wanted. Let's move on to setting values. This is all done using history.push, which takes a string with already added parameters. For example like this:



history.push('/path?item=my-item-data')


For more complex constructions, you will need to use a querystring:



const query = queryString.stringify({ item: "my-item-data" });
history.push(`/?${query}`);


or URLSearchParams:



const query = new URLSearchParams();
query.set("item", "my-item-data");
history.push(`/?${query}`);


Effects



Okay. Despite the fact that we always receive string data (and we need to parse it), there is also a problem if we expect a digit, and a word comes (the user is not prohibited from changing the query in the string), we will have to fence checks and push the value yourself.



Most of the pain comes when it is necessary that the request fields depend on the components that are now displayed, now each component will work with one global state, and change it at your discretion, relying on the already existing value, you will have to add not only your own values ​​to add , and also all the rest to be adjusted, something like this:



const oldQuery = queryString.parse(location.search);
const query = queryString.stringify({ item: "my-item-data" });
history.push(`/?${{...oldQuery,  ...query}}`);


Of course, most likely you will move this into a function, and it will already be more convenient to work with it. But then you will have to fence functions for reading values, checking values, somehow handling errors associated with the passed values ​​and even pushing them again, otherwise we changed the value for ourselves, and left the string the same.



You also need to clear the value after yourself later, of course history.push will do it for you, but it's much easier not to bother with it and let others do it instead of you.



Okay. What am I suggesting?



I think I did it for you, and in a more convenient way. Next, we will talk about the

react-location-query npm package , which may be worth your attention.



The package implements hooks and HOC components (just a wrapper over the hooks) to set the rules for how parameters work in the search bar, where we set the value in one of the components, or we can get it in any other component (even higher in the tree, but you shouldn't do that) ).



Example



For example, there is a UsersPage page with the UsersList and Controls components. UsersList is for loading and displaying a list of users, and Controls is for setting user filtering. Everything can be represented like this:



const UsersPage = () => {
  const [type] = useLocationField('type', 'github');

  return ...;
}

const UsersList = () => {
  const [page, setPage] = useLocationField('page', {
    type: 'number',
    initial: 1,
    hideIfInitial: true
  });
  const [limit, setLimit] = useLocationField('limit', {
    type: 'number',
    initial: 20,
    hideIfInitial: true
  });
  const [type] = useLocationField('type');

  return ...;
}

const Controls = () => {
  const [type, setType] = useLocationField('type');
 //     type  setType
  return ...;
}


As we can see, for the page and limit fields, we used an object with the following options:



  • type β€” ( , )
  • initial β€” ,
  • hideIfInitial β€” : , (.. ), ,




To customize the field and its value, there are other fields, for example, a callback (which returns a new value) in case of impossible parsing of the value (a string was passed, but a number / boolean value was expected). All these fields can be seen in the README on the npm package page or on github.Also a



small description of the hooks present:



  • useLocationField - hook for working with strictly one value
  • useLocationQuery - multi - value hook
  • useLocationQueryExtend - a hook for working with many values ​​whose data is outside the framework of the standards (for example json )
  • useLocationClear - a hook to get started, you need to put it in the root component (without it, the fields will not be cleared), or you don’t need to lay it down if there are already some of the hooks described above


Also, in addition to the hooks, there are HOC components that are their wrappers for the hooks.



Footer



This article was written in order to notify others about the presence of this package. There are many more tricks that I want to implement there (for example, enum value), while I'm waiting for feedback and information whether this package has at least a little right to life or is completely unnecessary.



All Articles