ba-react-fetch-api

0.12.60 • Public • Published

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);

Readme

Keywords

none

Package Sidebar

Install

npm i ba-react-fetch-api

Weekly Downloads

2

Version

0.12.60

License

ISC

Unpacked Size

699 kB

Total Files

175

Last publish

Collaborators

  • nide