How to Add Query Parameters to the URL in Next.js?
If you're building a web application with Next.js, adding query parameters to the URL is an important feature that can greatly enhance user experience. In this article, we will show you how to add query parameters to the URL in Next.js using the example of a simple SearchСategory
component.
We'll cover everything from creating a state and handling click events to updating the route and saving selected categories from the URL. So let's get started!
Add query parameters to the URL in Next.js step by step
Let`s create an array of categories and a Categories
component that renders the set of buttons. Each button contains the onClick
event that invokes the handleClick
function with the button key attribute.
const categories = [ { name: 'Category 1', key: 'category-1', }, { name: 'Category 2', key: 'category-2', },];
const Categories = () => { const handleClick = (key) => { ...the handleClick logic }
return ( <> {categories?.map((category) => ( <button key={category.key} type="button" onClick={() => handleClick(category.key)}
> {category.name} </button> ))} </> );};
Now, we need to create a state containing an array of selected categories and call the Next.js useRouter
hook in the component.
const [selectedCategories, setSelectedCategories] = useState([]);const router = useRouter();
Then create a function that adds and removes a category from the array and apply it in the handleClick
method.
const getUpdatedArray = (data, key) => { const current = data?.find((item) => item === key);
const updated = current ? data.filter((item) => item !== key) : [...data, key];
return updated;};
const handleClick = (key) => { const categories = getUpdatedArray(selectedCategories, key); setSelectedCategories(categories);};
Using the getUpdatedArray
function, we check if the given key exists in the selectedCategories
array. If not, we add it to the array; if it already exists, we remove it. Then we set the updated array into the state.
Updating the Route
We need to use the router object from the useRouter
hook to add categories to the URL as query parameters.
router.push({ ...router, query: { ...router.query, filter: categories.join(','), },},undefined, { shallow: true });
The first parameter is the URL
Since we need to stay on the current page, we keep the router's initial data using the spread operator and only add a new filter
query to the query parameters.
The second parameter is the "as" (optional)
It is a decorator for the path that changes the pathname to the browser bar and doesn`t navigate to another page. Defaults to URL. We set it to undefined
because changing the URL is not required.
The third parameter is the configuration options (optional)
By default, the router push
renders a new page and re-runs getStaticProps
, getServerSideProps
, or getInitialProps
whenever the path updates. The shallow
flag prevents these methods from being called and re-renders the current page without the load effect.
If the selected categories array is empty, we need to remove the filter query from the URL and update the router.
delete router.query.filter;router.push(router, undefined, { shallow: true });
As a result, in the handleClick
function, we get the following code:
const handleClick = (key) => { const categories = getUpdatedArray(selectedCategories, key); setSelectedCategories(categories);
if (!selectedCategories?.length) { delete router.query.filter; router.push(router, undefined, { shallow: true }); } else { router.push( { ...router, query: { ...router.query, filter: categories.join(','), }, }, undefined, { shallow: true }, ); }};
Now, it remains only to add the ability to save the selected categories from the URL when refreshing the page. A simple way is to set our query as the initial state of the selectedCategories
. But we can not do that because the useRouter
returns query parameters as undefined
on the first render.
To monitor whether or not the queries are populated, we need to check the router isReady property. It checks the router updates on the client side and returns true
if fields are ready to use.
useEffect(() => { if (!router?.isReady) return;
const categoryQuery = router?.query?.filter;
if (categoryQuery && !selectedCategories?.length) { setSelectedCategories(categoryQuery?.split(',')); }}, []);
We check if the router fields are ready or not, and if not, we do nothing. Otherwise, we convert the categories query in the array. And, if the query exists and the selected categories array is empty, we set it to the state.
And that is it! Now, we have a working component that adds query parameters to the URL using the Next.js router.
The life code example you can find here.
Conclusion
In conclusion, adding query parameters to the URL is an essential feature for web applications that can enhance user experience. With Next.js, it's relatively easy to implement this feature using the useRouter
hook. Stay connected with us to get more informative articles on Next.js.
We hope this article was helpful to you! Thanks for reading!