• This repository has been archived on 16/Jun/2020
  • Stars
    star
    195
  • Rank 199,374 (Top 4 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created about 8 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A library for managing state through query parameters in the URL in React

React URL Query

npm version Build Status


Using React Hooks? Check out use-query-params for managing URL query parameters via hooks.

Update 2019-09-13 use-query-params has been updated to have a HOC and a render props solution. I recommend using that library for any modern query param problems as it is more likely to be updated.


A library for managing state through query parameters in the URL in React. It integrates well with React Router and Redux and provides additional tools specifically targeted at serializing and deserializing state in URL query parameters. With React URL Query, you can create components where there is no difference in handling state from an external store like Redux and state from the URL.

Motivation

When developing web applications, it's really common to want to encode parts of the state in URL query parameters to capture what users are seeing on screen. Think of things like filters, toggles, selected items, and so on. Storing them in the URL allows users to easily link others to what they are seeing and facilitates discussion. React URL Query makes doing this really easy.

The current set of tools for React does not provide facilities for easy interaction with query parameters.

The fantastic library React Router is the standard for integrating URL changes in React applications and provides us access to the query parameters as an object, but the fields within are always represented as strings-- just as they appear in the URL. This makes sense, but means developers must work to decode the strings into the proper types depending on what is being stored in a given param (e.g. numbers, booleans, arrays, objects). Furthermore, when one wants to update the query parameters in the URL, React Router gives us functions to do so via context.router, but no facilities for encoding our values as strings.

The current front-runner for state management in React app's is Redux. When first dealing with encoding state in URL query parameters, it's common to wonder how to get them in sync with what is in the Redux store. Dan Abramov, Redux's creator, suggests that you don't do that. Instead, he puts forth the idea of decoding the query parameters in the mapStateToProps function (you can look into props.location.query if you're using React Router). However, when it comes to encoding changes to the query parameters back into the URL, we're back to calling router functions directly.

React URL Query is based off the idea that we can have an equivalent to mapStateToProps and mapDispatchToProps (see Redux's Usage with React) but for the URL. In fact, it allows you to provide mapUrlToProps and mapUrlChangeHandlersToProps when configuring components to do just that. You can decode URL query params into props in mapUrlToProps and you can encode them back into params through change handlers in mapUrlChangeHandlersToProps. This means the component code itself doesn't need to be aware of which props are managed by Redux and which props are managed by the URL-- it can just read props and call change handlers, and the application will update appropriately.

There are some very common patterns when encoding and decoding URL query parameters: each parameter has a type and a name in the URL and parameters of a given type should always be encoded or decoded the same way. It's cumbersome and repetitive to always create the map___ToProps functions to handle this common use case, so React URL Query provides a succinct way of describing URL query parameters through its urlPropsQueryConfig. You can just describe the type and names of the query parameters, and the decoded query params along with their change handlers will be passed in as props to the wrapped component.

Check it out below or in the other examples to see how it works.

Installation

npm install --save react-url-query

How do I use it?

A number of examples have been created demonstrating a variety of methods of using the library with different technologies. Here is the most basic form of using it in a component:

import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { addUrlProps, UrlQueryParamTypes } from 'react-url-query';

/**
 * Specify how the URL gets decoded here. This is an object that takes the prop
 * name as a key, and a query param specifier as the value. The query param
 * specifier can have a `type`, indicating how to decode the value from the
 * URL, and a `queryParam` field that indicates which key in the query
 * parameters should be read (this defaults to the prop name if not provided).
 *
 * Here we specify two props,  `bar` and `foo` that correspond to query parameters
 * `bar` and `fooInUrl` respectively. React URL Query will interpret URLs like
 * /app?bar=react&fooInUrl=137 and pass the props `{ bar: "react", foo: 137 }`
 * to the MainPage component.
 */
const urlPropsQueryConfig = {
  bar: { type: UrlQueryParamTypes.string },
  foo: { type: UrlQueryParamTypes.number, queryParam: 'fooInUrl' },
};

class MainPage extends PureComponent {
  static propTypes = {
    // URL props are automatically decoded and passed in based on the config
    bar: PropTypes.string,
    foo: PropTypes.number,

    // change handlers are automatically generated when given a config.
    // By default they update that single query parameter and maintain existing
    // values in the other parameters.
    onChangeFoo: PropTypes.func,
    onChangeBar: PropTypes.func,
  }

  static defaultProps = {
    foo: 123,
    bar: 'bar',
  }

  render() {
    const { foo, bar, onChangeFoo, onChangeBar } = this.props;

    return (
      <div>
        <div>
          foo={foo}
          <button onClick={() => onChangeFoo(999)}>Set foo to 999</button>
        </div>
        <div>
          bar={bar}
          <button onClick={() => onChangeBar('testing')}>
            Set bar to "testing"
          </button>
        </div>
      </div>
    );
  }
}

/**
 * Use the addUrlProps higher-order component to hook-in react-url-query.
 */
export default addUrlProps({ urlPropsQueryConfig })(MainPage);

If you prefer, instead of using a urlPropsQueryConfig you can provide the functions mapUrlToProps and mapUrlChangeHandlersToProps, as shown in the basic-mapUrlToProps example.

You'll also need to configure which history to use, typically done wherever you initialize your application. Examples of doing this with different setups are shown in the examples section.

If you are using react-router, how you link in the history depends on the version.

React Router v2

import { configureUrlQuery } from 'react-url-query';
import { browserHistory } from 'react-router'

configureUrlQuery({ history: browserHistory });

React Router v4

import { RouterToUrlQuery } from 'react-url-query';
import Router from 'react-router/BrowserRouter';

ReactDOM.render(
  <Router>
    <RouterToUrlQuery>
      <App />
    </RouterToUrlQuery>
  </Router>,
  document.getElementById('root')
);

React Router v5

import { RouterToUrlQuery } from 'react-url-query';
import { 
  BrowserRouter as Router, 
  __RouterContext as RouterContext 
} from 'react-router-dom';

ReactDOM.render(
  <Router>
    <RouterToUrlQuery routerContext={RouterContext}>
      <App />
    </RouterToUrlQuery>
  </Router>,
  document.getElementById('root')
);

Not using React Router. If you're not using react-router, you'll need to instantiate the history yourself manually:

import { configureUrlQuery } from 'react-url-query';
import createHistory from 'history/createBrowserHistory';
const history = createHistory();

configureUrlQuery({ history });

Examples

Development

During development of examples, it can be helpful to have a watch running automatically rebuilding the package when changes take place. To get this running run:

npm run dev

Building

npm run build

Linting

npm run lint

To lint examples, run:

npm run lint:examples

Testing

npm run test

To test examples, run:

npm run test:examples

Working on docs

When editing the docs, it helps to have a dev server watching changes. To do this, run:

npm run docs:watch

To build the docs, run:

npm run docs:build

To publish the docs, run:

npm run docs:publish

License

MIT

More Repositories

1

use-query-params

React Hook for managing state in URL query parameters with easy serialization.
TypeScript
2,133
star
2

tidy

Tidy up your data with JavaScript, inspired by dplyr and the tidyverse
TypeScript
723
star
3

d3-interpolate-path

Interpolates path `d` attribute smoothly when A and B have different number of points.
JavaScript
315
star
4

d3-line-chunked

Create lines that indicate where data is missing with gaps or differently styled chunks/line segments.
JavaScript
120
star
5

3dpie

gaudy 3d pie generator in react and three.js
JavaScript
115
star
6

serialize-query-params

A javascript library for simplifying encoding and decoding URL query parameters
TypeScript
71
star
7

vis-utils

A collection of utility functions for helping with data visualization
JavaScript
51
star
8

linked-highlighting-react-vega-redux

Example of doing linked highlighting with React, Vega, and Redux
JavaScript
51
star
9

react-express-example

A basic example of using Express and Facebook's React for both client-side and server-side rendering.
JavaScript
45
star
10

p5js-ccapture

An example of using p5.js with CCapture.js for exporting frames
HTML
44
star
11

deckgl-point-animation

Demo of animating points in deck.gl
JavaScript
40
star
12

linked-highlighting-react-d3-reflux

An example of doing linked highlighting using React, d3.js and Reflux
JavaScript
39
star
13

d3-scale-interactive

An interactive UI for editing d3 v4 scales in your browser
JavaScript
36
star
14

react-map-demo

Created for ReactJS Boston Meetup, a demo of using react-map-gl and deck.gl to draw a basic map with some different layers.
JavaScript
30
star
15

react-taco-table

A table component for React based on column configuration ๐ŸŒฎ
JavaScript
30
star
16

react-basic-vis-examples

A few basic visualization examples that build on each other, using React and D3.js.
JavaScript
28
star
17

react-computed-props

A higher-order component for React to add computed or derived props to the wrapped component for better performance.
JavaScript
26
star
18

peterbeshai.com

HTML
15
star
19

cra-snowpack

Example of using Snowpack's dev server in a Create-React-App app
JavaScript
12
star
20

beshai-makes-code

Code for BeshaiMakes.com Articles
HTML
8
star
21

shots3D

Render basketball shots from the NBA using WebGL
JavaScript
6
star
22

recreating-the-past

Sketches for the Recreating the Past class at the MIT Media Lab (Fall 2019)
C++
5
star
23

stats

Examples for doing stats on experimental data
R
4
star
24

geo-explore

Simple demonstrative examples of mapping techniques for the web
HTML
3
star
25

d3-webpack-loader

Automatically bundle D3 v4 modules under a single `d3` import with D3 Webpack Loader.
JavaScript
3
star
26

rhombus

Rhombus Classroom Synchronous Participation System
Shell
2
star
27

react-library-starter

A starting place for creating a React library or component to share with others
JavaScript
2
star
28

react-autosize

Component to automatically provide width and height props to its child
JavaScript
2
star
29

react-auto-width

Set the width of a Reactjs component to its parent's width
JavaScript
2
star
30

nba-draft

JavaScript
2
star
31

rhombus-id-server

ID Server for Rhombus Classroom Synchronous Participation System
JavaScript
1
star
32

rhombus-web-app-basic

Barebones Web App for Rhombus Classroom Synchronous Participation System
JavaScript
1
star
33

rhombus-web-app-game-theory

Web App with Game Theory games for Rhombus Classroom Synchronous Participation System
JavaScript
1
star
34

rhombus-clicker-server

Clicker Server for Rhombus Classroom Synchronous Participation System
Java
1
star
35

tree-csv

Explore a CSV containing hierarchical data as a tree
JavaScript
1
star
36

rhombus-web-framework

Web Framework for Rhombus Classroom Synchronous Participation System
JavaScript
1
star
37

rhombus-web-app-experiment

Web App for 7-Segment Display Recognition Experiment for Rhombus Classroom Synchronous Participation System
JavaScript
1
star
38

protoweb

Web prototype scaffolding and hot-reloading server
JavaScript
1
star
39

rhombus-web-app-sandbox

Sandbox for various apps for Rhombus Classroom Synchronous Participation System
JavaScript
1
star
40

rhombus-clicker-server-filter-multiple-instructor

Multiple Instructor filter for the Clicker Server for Rhombus Classroom Synchronous Participation System
Java
1
star
41

rhombus-grunt-socket-server

HTTP/Socket.io server used by Rhombus Classroom Synchronous Participation System
JavaScript
1
star