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

ba-react-fetch-api

v0.12.60

Published

Data fetching API

Downloads

28

Readme

Fetch data from BluAvenu API

This package is aimed to provide cross platform (web/native) methods for fetching data from BluAvenu API server. It also adds some layer of abstraction allowing developers to call APIs using aliases instead of directly specifying API url paths. It is based on redux-api.

Index

Installation

npm install ba-react-fetch-api --save

Setup

Because of specificity of redux-api lib there are several steps required before using FetchAPI in real code:

  • desrcibe data sources
  • setup reducers
  • define some helper functions.

Suggest you do all these operations in a single file e.g. rest/index.js.

Data Sources

In order to setup reducers which are utilized for storing fetched data in redux store you need to describe sources of data. These are not reducers, but an array of objects which will be used for FetchAPI reducer init.

Example:

  export const sources = [
    {entity: 'campaigns', key: 'campaigns'},
    {entity: 'cases', key: 'cases'},
    {entity: 'contacts', key: 'contacts'},
    {entity: 'relatedContacts', key: 'relatedContacts'},

    {
      entity: 'contact',
      key   : 'contact',

      reducers: [detailsReducer({
        modelStorePath: 'fetchApi.contact.data',
        moduleName    : 'contact',
      })],
    },
  ];

Data source options are:

  • entity — names of entities is a limited set which is predefined in FetchAPI.
  • key — user defined name. Will be used for as redux store key name. E.g. you can use contacts for main list of Contacts and related_contacts for lists of Contacts related to currently active app page.
  • reducers — array of extra reducers applied to fetched data.

Reducers

In your root reducer function put this:

import {sources as dataSources} from './rest';
import {reducers as fetchApiReducers} from 'ba-react-fetch-api';

combineReducers(
  ...,

  fetchApi: fetchApiReducers(dataSources),
  
  ...,
)

Helpers

redux-api adds some compexity issues. In order to avoid them and make using FetchAPI easier helper methods introduced and suggested to be used along with FetchAPI. Setup them in rest/index.js as mentioned below a long with data sources code from previous section:

import _ from 'lodash';
import {hoc as fetchApiHoc} from 'ba-react-fetch-api';
import {restByKey} from 'ba-react-fetch-api';
import settings from 'settings';

const
  defaultParams = params => ({...params, baseURL: settings.API_PROXY_URL});

export const sources = [
  {entity: 'campaigns', key: 'campaigns'},
  {entity: 'cases', key: 'cases'},
  {entity: 'contacts', key: 'contacts'},
  {entity: 'relatedContacts', key: 'relatedContacts'},

  {
    entity: 'contact',
    key   : 'propertyOwner',

    reducers: [detailsReducer({
      modelStorePath: 'fetchApi.contact.data',
      moduleName    : 'contact',
    })],
  },
];

// Here come helpers
export const fetchApiList = params => fetchApiHoc.list(defaultParams(params)),
export const fetchApiDetails = params => fetchApiHoc.details(defaultParams(params)),

export const rest = params => restByKey({
  baseURL: settings.baseURL,
  key    : _.isObject(params) ? params.key : params,
  entity : params.entity,
  sources
});

restByKey()

Initializes redux-api rest object, which provides methods for doing http requests.

Using rest() from the code above following example will do a GET-request and put returned data into fetchApi.contacts key of redux store (considering reducers were defined like in an example above):

rest({entity: 'contatcs', key: 'related_contacts'}).sync();

// Considering you have a defined source object, with key="contacts"
rest({key: 'contatcs'}).sync()

// Pass just string, which will find a source with key equal passed string, or create one with
// entity and key equal passed string
rest('contatcs').sync()

Usage

Higher Order Component

Its goal is to provied wrapped component with data fetched and stored in redux store. And also to provide methods for fetching data or performing CRUD requests.

Porperties and methods which came to wrapped component from FetchAPI hocs are stored in props.faFetched.<key param>.

Apply it like this:

import _ from 'lodash';
import {fetchApiList} from 'rest';

const
  ContactsList = props => <div>
    {_.map(props.faFetched.contacts.data, contact => <div>{contact.personal.first_name}</div>)}
  </div>;

compose(
  fetchApiList({
    entity: 'contacts',

    // These are GET-request params
    queryParams: props => {search: props.searchValue},

    filters: 'filter.savedFilters',
    key    : 'contacts',
    page   : `incrementalList.someUniqueId.page`,
    sorting: `table.someUniqueId.sorting`,
  }),
)(ContactsList);

List HOC

import {hoc} from 'ba-react-fetch-api';

compose(
  hoc.list(...),
)();

Params

  • entity: string — due to some design decisions you have to duplicate entity name when applying a hoc
  • key: string — the one defined in data sources array
  • filters?: string | Array — filtering params values or path in redux store
  • fetchOnMount?: boolean — if passed true data will be fetched during component mount, otherwise fetch will only happen when hoc params changes
  • page?: string | number — current page value or its path in redux store
  • sorting?: Object — sorting params values or path in redux store
  • statePath?: string — path to redux store of FetchAPI reducer, default is fetchApi
  • queryParams?: (props: Object) => Object — extra params applied to GET query string or POST/PUT body, passed with component props when called
  • urlParams?: (props: Object) => Object — url pattern params, like {id: '1a'} to be applied as :id in such url pattern /contacts/:id, passed with component props when called.

For data structure expected for filters, page and sorting refer to types annotations — https://github.com/chunkytae/ba-react-fetch-api/blob/master/FetchAPI/hoc/list.js

Methods

  • data — fetched data array
  • reset() — reset data in redux store
  • sync(urlParams: Object, params: Object) — fetch data.

Filtering

As mentioned above in order to apply filtering to list hoc pass string representing redux store path or array of objects in filters param.

Filter item types definitions can be found here.

Important Currently filter item data structure includes two similar properties value and compiledValue. Always use value. compiledValue is deprecated.

Value format

value must be passed as string and can take either string/numeric or range or set of options:

  • range
    • date [2005-08-09T15:31:42+03:30,2005-08-09T18:20:42+03:30]
    • numeric [55,170]
  • set — [585be5845d0000d1057c4174, 592b2c814f0000993428eb47, 592b105b4f0000243328e9fc].

In case of date value format it accepts set of special options:

  • yesterday
  • today
  • tomorrow
  • next_week
  • last_week
  • next_month
  • last_month.

Possible operator options

Set of operator options depend on filter value type. It means that operators will differ for string and date values:

  • numeric — eq, not-eq, lt, lt-eq, gt, gt-eq, empty, non-empty
  • string — is, is-not, contains, not-contain, starts-with, ends-with, empty, non-empty
  • dates — eq, not-eq, lt, lt-eq, gt, gt-eq, empty, non-empty
  • lookup — value which accepts predefined set of ids, like in value example above. Options are — in, not-in, empty, non-empty.

Sorting

Only sorting by single field is available. Takes the string representing redux store path or following object:

// {column: string, order: asc | desc}
{column: 'meta._created', order: 'desc'}

Details HOC

import {hoc} from 'ba-react-fetch-api';

compose(
  hoc.details(...),
)(Component);

Params

  • entity: string — due to some design decisions you have to duplicate entity name when applying a hoc
  • key: string — the one defined in data sources array
  • fetchOnMount?: boolean — if passed true data will be fetched during component mount, otherwise fetch will only happen when hoc params changes
  • statePath?: string — path to redux store of FetchAPI reducer, default is fetchApi
  • queryParams?: (props: Object) => Object — extra params applied to GET query string or POST/PUT body, passed with component props when called
  • urlParams?: (props: Object) => Object — url pattern params, like {id: '1a'} to be applied as :id in such url pattern /contacts/:id, passed with component props when called.

Methods

  • data — fetched data object
  • delete(urlParams: Object) — send DELETE request
  • etag — this token is required for every PUT request, meaning for every single data update request
  • post(urlParams: Object, params: {body: string, headers: Object}) — send POST request. Use params for sending request body and headers. body must a valid stringified json.
  • put(urlParams: Object, params: {body: string, headers: Object}) — same as POST.
  • reset() — reset data in redux store
  • sync(urlParams: Object, params: Object) — fetch data.

Calling redux-api actions directly

In some cases you need to perform single API request but do not require any fetched data to be applied to component. For such situations you can dispatch redux-api actions directly, without applying hoc to your component.

Import helper function from rest/ and use it like this:

import _ from 'lodash';
import {fetchApiList, rest} from 'rest';

const
  ContactsList = props => <div>
    {_.map(props.faFetched.contacts.data, contact => <div>
      {contact.personal.first_name}
      <button onClick={() => props.deleteContact(contact._id)}>Delete</button>
    </div>)}
  </div>;

compose(
  fetchApiList({
    entity: 'contacts',

    // These are GET-request params
    fetchParams: props => {search: props.searchValue},

    filters: 'filter.savedFilters',
    key    : 'contacts',
    page   : `incrementalList.someUniqueId.page`,
    sorting: `table.someUniqueId.sorting`,
  }),
  
  withHandlers({
    deleteContact: props => id => rest('contact').delete({id: id}, error => {
      if(!error)
        console.log('Item removed!');
    }),
  }),
)(ContactsList);

Batch request

Batch API allows client to put several API calls into a single HTTP request having multiple responses returned in single one.

In order to use batch requests:

Update your data sources

export const sources = [
  {entity: 'batch', key: 'opportunitiesStages'},
];

Call it in a component

import {restByKey} from 'ba-react-fetch-api';
import {sources} from 'your/data/sources/file';

restByKey({
  key: 'opportunitiesStages',
  sources: sources
}).post(
    null,

    {body: JSON.stringify([
      {
        url: 'http://104.236.30.5:9999/crm/v1/contacts',
        key: 'contacts',
      },
      {
        url: 'http://104.236.30.5:9999/crm/v1/accounts',
        key: 'accounts',
      }
    ])}
);

Now in redux store you have multiple responses in the format of:

[
  {
    "contacts": {}
  },

  {
    "accounts": {}
  }
]

Usage via hoc

import {connect} from 'react-redux';
import {hoc as fetchApiHoc} from 'ba-react-fetch-api';

compose(
  fetchApiHoc.batch({
    entity      : 'batch',
    fetchOnMount: true,
    key         : 'myBatch',

    requests: () => ([
      {
        url: 'http://45.55.45.137:9999/crm/v1/contacts',
        key: 'contacts',
      },

      {
        url: 'http://45.55.45.137:9999/crm/v1/accounts',
        key: 'accounts',
      }
    ])
  }),
  
  connect(state => ({
    requests: state.fetchApi.myBatch,
  })),
)(SomeComponent);