Skip to main content


A component from the Recoil Sync library to sync atoms using the syncEffect() or urlSyncEffect() atom effects with the browser URL.

function RecoilURLSync(props: {
storeKey?: string,

location: LocationOption,

serialize: mixed => string,
deserialize: string => mixed,

browserInterface?: BrowserInterface,
children: React.Node,
}): React.Node

The storeKey is used to match up which atoms should sync with this external store.

URL Location

The location prop specifies what part of the URL to sync with:

type LocationOption =
| {part: 'href'}
| {part: 'hash'}
| {part: 'search'}
| {part: 'queryParams', param?: string};
  • queryParams with no param - Atoms sync with individual query params
  • queryParams with a param - Atoms are encoded in a single query param
  • search - State is encoded with the entire query search string
  • hash - State is encoded in the anchor tag
  • href - Escape to be able to encode the entire URL. Care must be taken to provide a valid and legal URL.


See the URL Persistence Guide for examples.

Custom serialization

The serialize() and deserialize() callbacks can provide custom serializations:

  serialize: x => JSON.stringify(x),
deserialize: x => JSON.parse(x),

These callbacks should be memoized with something like useCallback() to avoid re-parsing the URL with every render. Depending on the location in the URL that is synced with, the callbacks may be either called with individual values or with an object containing multiple values. Wrappers such as <RecoilURLSyncJSON> and <RecoilURLSyncTransit> provide these for you.

Browser Abstraction

By default <RecoilURLSync> will sync directly with the URL in the browser. However, you may override this by providing a custom browser interface implementation. This is also important to provide if you may be executing in a server-side rendering (SSR) environment.

type BrowserInterface = {
replaceURL?: string => void,
pushURL?: string => void,
getURL?: () => string,
listenChangeURL?: (handler: () => void) => (() => void),