DEV Community

Stephanie Eckles
Stephanie Eckles

Posted on

How to Use URL Query String Parameters in Gatsby

In Gatsby, leverage Reach Router's useLocation hook along with the query-string package to parse URL query string parameters and use the value to update state.

First, install:

npm install @reach/router query-string
Enter fullscreen mode Exit fullscreen mode

Reach Router is used by Gatsby, but you'll need it in your package.json if linters are in use.

In this example, change the user's selected theme, or expand to any values you need from the URL parameters, available on location.search from the useLocation hook.

import * as React from 'react';

import { useLocation } from '@reach/router';
import queryString from 'query-string';

const getSelectedTheme = (query) => {
  const fallback = 'light';

  if (query) {
    const queriedTheme = queryString.parse(query);
    const { theme } = queriedTheme;

    // Ensure a valid expected value is passed
    if (['light', 'dark'].includes(theme)) {
      return theme;
    }

    return fallback;
  }

  return fallback;
};

const UserTheme = () => {
  const location = useLocation();
  const defaultTheme = (location.search && getSelectedTheme(location.search)) || 'light';
  const [theme, setTheme] = React.useState(defaultTheme);

  // rest of component, maybe creates/updates context, or updates a form setting

};
Enter fullscreen mode Exit fullscreen mode

Available as a gist >

This method is an update to use hooks and a functional component based on the example in the article How to Get Query String Parameter Values in Gatsby by Christopher Fitkin.

Top comments (2)

Collapse
 
dandv profile image
Dan Dascalescu

Is it necessary to useLocation? Gatsby passes location via props to any component.

Collapse
 
5t3ph profile image
Stephanie Eckles

If I'm understanding correctly, location is provided to "page" components, whereas this is a functional component/hook combo for flexibility in accessing this information.

The main reason for the additional install is this came from a project using Typescript so it needed to be explicitly defined in the package to avoid linting errors/leverage intellisense.

But thanks for bringing that to my attention, I'm sure it would be useful in other scenarios!