npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-query-sync

v0.1.10

Published

Synchronise URL query parameters and redux state.

Downloads

5,964

Readme

redux-query-sync

Treat the URL query parameters as exposed variables of your Redux state. For example, /mypage.html?p=14 could correspond to a state object containing {pageNumber: 14}.

Any changes to the store state are reflected in the URL. Vice versa, if the URL is changed using the history module, the changed parameters are updated in the store state.

Alternatives

Similar modules exist, which you might prefer in some scenarios:

Otherwise, keep reading.

Install

npm install redux-query-sync

…or equivalent.

Usage

As a minimal example, let's say we want to synchronise query parameter dest with the value of the state's route.destination field, to parse/make URLs such as directions.html?dest=Amsterdam.

Minimal example

import ReduxQuerySync from 'redux-query-sync'

ReduxQuerySync({
    store, // your Redux store
    params: {
        dest: {
            // The selector you use to get the destination string from the state object.
            selector: state => state.route.destination,
            // The action creator you use for setting a new destination.
            action: value => ({type: 'setDestination', payload: value}),
        },
    },
    // Initially set the store's state to the current location.
    initialTruth: 'location',
})

Note that redux-query-sync does not modify the state, but lets you specify which action to dispatch when the state should be updated. It does modify the location (using history.pushState/replaceState), but ensures to only touch the parameters you specified.

Let's look at a more elaborate example now. We sync the query parameter p with the value of the state's pageNumber field, which includes a mapping between string and integer.

Longer example

import ReduxQuerySync from 'redux-query-sync'

ReduxQuerySync({
    store,
    params: {
        p: {
            selector: state => state.pageNumber,
            action: value => ({type: 'setPageNumber', payload: value}),

            // Cast the parameter value to a number (we map invalid values to 1, which will then
            // hide the parameter).
            stringToValue: string => Number.parseInt(string) || 1,

            // We then also specify the inverse function (this example one is the default)
            valueToString: value => `${value}`,

            // When state.pageNumber equals 1, the parameter p is hidden (and vice versa).
            defaultValue: 1,
        },
    },
    initialTruth: 'location',

    // Use replaceState so the browser's back/forward button will skip over these page changes.
    replaceState: true,
})

Note you could equally well put the conversion to and from the string in the selector and action creator, respectively. The defaultValue should then of course be a string too.

See some examples in the wild:

API

ReduxQuerySync()

Sets up bidirectional synchronisation between a Redux store and window location query parameters.

| Param | Type | Description | | --- | --- | --- | | options.store | Object | The Redux store object (= an object {dispatch, getState}). | | options.params | Object | The query parameters in the location to keep in sync. | | options.params[].action | function: value => action | The action creator to be invoked with the parameter value. Should return an action that sets this value in the store. | | options.params[].selector | function: state => value | The function that gets the value given the state. | | [options.params[].defaultValue] | * | The value corresponding to absence of the parameter. You may want this to equal the state's default/initial value. Default: undefined. | | [options.params[].valueToString] | function | Specifies how to cast the value to a string, to be used in the URL. Defaults to javascript's automatic string conversion. | | [options.params[].stringToValue] | function | The inverse of valueToString. Specifies how to parse the parameter's string value to your desired value type. Defaults to the identity function (i.e. you get the string as it is). | | options.initialTruth | string | If set, indicates whose values to sync to the other, initially. Can be either 'location' or 'store'. If not set, the first of them that changes will set the other, which is not recommended. Usually you will want to use location. | | [options.replaceState] | boolean | If truthy, update location using history.replaceState instead of history.pushState, to not add entries to the browser history. Default: false | | [options.history] | Object | If you use the 'history' module, e.g. when using a router, pass your history object here in order to ensure all code uses the same instance. |

Returns: a function unsubscribe() that can be called to stop the synchronisation.

ReduxQuerySync.enhancer()

For convenience, one can set up the synchronisation by passing an enhancer to createStore.

Example

const storeEnhancer = ReduxQuerySync.enhancer({
    params,
    initialTruth,
    replaceState,
})
const store = createStore(reducer, initialState, storeEnhancer)

Arguments to ReduxQuerySync.enhancer are equal to those for ReduxQuerySync itself, except that store can now of course be omitted. With this approach, you cannot cancel the synchronisation.