ReachRouterStorage gives you an easy to use binding for working with Reach Router. By default it stores your data in the query string, but can be configured to also get and set pathname.

It can only store data that is serializable and stored as a string, such as via JSON.stringify().

It is controlled, meaning that it will update immediately whenever the data source (the query string) changes.

import ReachRouterStorage from 'react-cool-storage/ReachRouterStorage';


    // optional
    method?: string = "push",
    pathname?: boolean = false,
    deconstruct?: (data: any) => any,
    reconstruct?: (data: any) => any,
    parse?: (data: string) => any,
    stringify?: (data: any) => string,
    memoize?: boolean = true
  • method ?: string = "push"

    The history method to use. Can be “push” or “replace”. Defaults to "push".

  • pathname ?: boolean = false

    When set to true, the Reach Router pathname will be included in the value at value.pathname. The pathname can then also be set using onChange({pathname: "???"}). Defaults to false.

  • deconstruct ?: (data: any) => any

    Can be used to convert data into a serializable format. It is called before ReachRouterStorage stringifies data when a change occurs.

  • reconstruct ?: (data: any) => any

    Can be used to convert data from a serializable format into richer data types. It is called after ReachRouterStorage has parsed its data. It is given the parsed object.

  • parse ?: (data: string) => any = JSON.parse()

    A function that is called on the value to turn it from a string into a data shape. Defaults to JSON.parse().

  • stringify ?: (data: any) => string = JSON.parse()

    A function that is called on the value to turn it from a data shape into a string. Defaults to JSON.stringify().

  • memoize ?: (data: any) => string = JSON.parse()

    When true, the result of parse will be memoized deeply using deep-memo so that references to objects and arrays will remain unchanged unless their values change. This allows parts of the value data object to work seamlessly with React pure components. When false, new objects and arrays will be created every time props change, but if a large amount of data is being parsed then disabling memoization can reduce the computation time of the parsing step. Defaults to true.


ReachRouterStorage requires three resources:

  • window.URLSearchParams must exist. Polyfills are available if you need to support older browsers.
  • A Reach Router navigation function to be passed into config
  • A Reach Router location object as a prop


ReachRouterStorage requires these props to be passed to it:

  • A Reach Router location object as a prop

Example using hooks

import React from 'react';
import {useState} from 'react';
import ReactCoolStorageHook from 'react-cool-storage';
import ReachRouterStorage from 'react-cool-storage/ReachRouterStorage';
import {navigate} from 'gatsby';

const useStorage = ReactCoolStorageHook(
        method: "replace"

export default (props) => {
    let query = useStorage(props);

    return <div>
        <label>query string "foo"</label>
            value={ || ""}
            onChange={(event) => query.onChange({
                foo: event.currentTarget.value
        <label>query string "bar"</label>
            value={ || ""}
            onChange={(event) => query.onChange({
                bar: event.currentTarget.value