Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

redux-query

Package Overview
Dependencies
Maintainers
1
Versions
78
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

redux-query

Library for React/Redux apps that use REST APIs to synchronize and manage network state

  • 1.0.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
14K
decreased by-1.25%
Maintainers
1
Weekly downloads
 
Created
Source

redux-query

Travis npm Codecov

redux-query is a library for React/Redux apps that use REST APIs to synchronize and manage network state.

With redux-query you can:

  • Declare your network dependencies right next to your React components. Data is requested automatically when components mount. When components update and unmount, in-flight requests are automatically cancelled.
  • Trigger server-side changes (mutations) by dispatching regular Redux actions.
  • Have a consistent, minimal-boilerplate interface for all network-related state.
  • Transform and normalize data to avoid duplicate state.
  • Perform optimistic updates.
  • Use in conjunction with other Redux libraries redux-thunk and redux-saga.
  • Debug network state and actions with Redux dev tools (e.g. redux-logger).

Getting Started

Install redux-query via npm:

$ npm install --save redux-query

Add the entitiesReducer and queriesReducer to your combined reducer.

Include the queryMiddleware to your store's applyMiddleware call. queryMiddleware requires two arguments: a function (selector) that returns entities state, and a function for the queries state.

For example:

import { applyMiddleware, createStore, combineReducers } from 'redux';
import { entitiesReducer, queriesReducer, queryMiddleware } from 'redux-query';
import createLogger from 'redux-logger';

export const getQueries = (state) => state.queries;
export const getEntities = (state) => state.entities;

const reducer = combineReducers({
    entities: entitiesReducer,
    queries: queriesReducer,
});

const logger = createLogger();
const store = createStore(
    reducer,
    applyMiddleware(queryMiddleware(getQueries, getEntities), logger)
);

Usage and API

Requests and mutations

There are two types of queries with redux-query: "requests" and "mutations". Requests are for reading values from HTTP endpoints. Mutations are for HTTP endpoints that change network state – the "C", "U", and "D" in "CRUD".

Requests can be triggered from the connectRequest higher-order component or a requestAync action. Mutations are triggered by dispatching a mutateAsync action.

By default, requests are GETs and mutations are POSTS.

Query configs

Query configs are objects used to describe how redux-query should handle the request or mutation.

Query configs for requests have the following options:

NameTypeRequired?Description
urlstringyesThe URL for the HTTP request.
transformfunctionFunction that transforms the response data to an entities object where keys are entity IDs and values are entity data. Can be used to normalize data.
updateobjectyesObject where keys are entity IDs and values are update functions.
bodyobjectThe request body.
forcebooleanPerform the request even if we've already successfully requested it.
queryKeystringThe identifier used to identify the query metadata in the queries reducer. If unprovided, the url and body fields are serialized to generate the query key.
metaobjectVarious metadata for the query. Can be used to update other reducers when queries succeed or fail.
optionsobjectOptions for the request. Set options.method to change the HTTP method.

Query configs for mutations are slightly different. They have the following options:

NameTypeRequired?Description
urlstringyesThe URL for the HTTP request.
transformfunctionFunction that transforms the response data to an entities object where keys are entity IDs and values are entity data. Can be used to normalize data.
updateobjectyesObject where keys are entity IDs and values are update functions.
optimisticUpdateobjectObject where keys are entity IDs and values are functions that provide the current entity value. The return values are used to update the entities store until the mutation finishes.
bodyobjectThe HTTP request body.
queryKeystringThe identifier used to identify the query metadata in the queries reducer. If unprovided, the url and body fields are serialized to generate the query key.
optionsobjectOptions for the request. Set options.method to change the HTTP method.

transform functions

transform functions let you process and normalize response data before it is passed to the update step. They have the following signature:

(responseJson: ?Object, responseText: string) => { [key: string]: any }

If your data is normalized on the server, you may not need to use this function.

update functions

update functions are responsible for reconciling response data with the existing entities reducer data for the given entity ID. They have the following signature:

(prevValue: any, transformedValue: any) => any

The prevValue is the whatever value is selected from the entities reducer for the respective entity ID. The returned value from this function will become the new value for the entity ID in the entities reducer.

optimisticUpdate functions

optimisticUpdate functions are just like update functions except they only pass the prevValue:

(prevValue: any) => any

connectRequest

Use the connectRequest higher-order component to declare network dependencies for a React component. connectRequest takes a function that transforms the component props to a query config. Example usage:

import { connectRequest, querySelectors } from 'redux-query';

class Dashboard extends Component {
    ...
}

const DashboardContainer = connectRequest((props) => ({
    url: `/api/dashboard/${props.dashboardId}`,
    update: {
        chartsById: (prevCharts, dashboardCharts) => ({
            ...prevCharts,
            ...dashboardCharts,
        }),
        dashboardsById: (prevDashboards, dashboards) => ({
            ...prevDashboards,
            ...dashboards,
        }),
    },
}))(Dashboard);

const mapStateToProps = (state, props) => {
    return {
        dashboard: getDashboard(state, props),
    };
};

export default connect(mapStateToProps)(DashboardContainer);

connectRequest passes an extra prop to the child component: forceRequest. Calling this function will cause the request to be made again. This may be useful for polling or creating an interface to trigger refreshes.

mutateAsync

Dispatch mutateAsync Redux actions to trigger mutations. Example usage with a react-redux-connected component:

// src/queries/dashboard.js

export const createUpdateDashboardQuery = (dashboardId, newName) => ({
    url: `/api/${dashboardId}/update`,
    body: {
        name: newName,
    },
    update: {
        dashboardsById: (prevDashboardsById, newDashboardsById) => ({
            ...prevDashboardsById,
            ...newDashboardsById,
        }),
    },
});

// src/actions/dashboard.js

import { createUpdateDashboardQuery } from '../queries/dashboard';

export const updateDashboard = (dashboardId, newName) => {
    return mutateAsync(createUpdateDashboardQuery(dashboardId, newName));
};

// src/selectors/dashboard.js

export const getDashboard = (state, { dashboardId }) => {
    if (state.entities.dashboardsById) {
        return state.entities.dashboardsById[dashboardId];
    } else {
        return null;
    }

// src/components/Dashboard.jsx

import { connect } from 'react-redux';

import { updateDashboard } from '../actions/dashboard';
import { getDashboard } from '../selectors/dashboard';

class Dashboard extends Component {
    ...
}

const mapStateToProps = (state, props) => {
    return {
        dashboard: getDashboard(state, props),
    };
};

const mapDispatchToProps = (dispatch, props) => {
    return {
        changeName: (newName) => {
            dispatch(updateDashboard(props.dashboardId, newName));
        },
    };
};

export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);

When dispatching a mutateAsync action, you can Promise-chain on the returned value from dispatch:

const mapDispatchToProps = (dispatch, props) => {
    return {
        changeName: (newName) => {
            dispatch(updateDashboard(props.dashboardId, newName)).then((result) => {
                if (result.status !== 200) {
                    dispatch(showUpdateDashboardFailedNotification(props.dashboardId));
                }
            });
        },
    };
};

requestAsync

Similarly to how mutations are triggered by dispatching mutateAsync actions, you can trigger requests by dispatching requestAsync actions.

Example

A fork of the redux Async example is included. To run:

$ cd examples/async
$ npm install
$ npm run start

Keywords

FAQs

Package last updated on 13 Feb 2017

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc