How to Add Query Parameters to the URL in Next.js?

April 27th, 2023
Share:
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!

Subscribe icon

Subscribe to our Newsletter

Sign up with your email address to receive latest posts and updates