Connect

The data-fetching decorator for Lore

first

This blueprint returns the first resource matching the provided criteria.

This is useful when you know an API has certain queries that will only ever return 0 or 1 results, but you do not know the id of the resource you're looking for (or whether it exists at all).

Additionally, you could also use this blueprint to the return the most recent resource a user created, by saying "give me a list of data, sort by the date that data was created, and give me the first thing in that list".

Usage

Example usage is below:

import { connect } from 'lore-hook-connect';

connect((getState, props) => {
  return {
    tweet: getState('tweet.first', {
      where: {
        user: 1
      },
      pagination: {
        _sort: 'createdAt',
        _order: 'desc'
      }
    })
  }
})

When invoked, this blueprint will return one of three responses.

Response #1: Data is Fetching

If the query has never been asked, the response will look like this (because it's being retrieved from the API):

const tweet = {
  state: PayloadStates.FETCHING
};

Response #2: Data is Found

If the API response contains data, this will return the first resource in the list:

const tweet = {
  id: 1,
  cid: '1',
  state: PayloadStates.RESOLVED,
  data: {
    name: 'resource name'
  }
};

Response #3: Data is Not Found

If the API response contains NO data, this will return a resource declaring nothing was found, as well as the meta and query parameters from the collection that describe what question was asked.

const tweet = {
  id: undefined,
  cid: undefined,
  state: PayloadStates.NOT_FOUND,
  data: {},
  error: {},
  meta: { /* if applicable */ },
  query: { /* if applicable */ }
};

Blueprint

export default _.defaultsDeep({

  defaults: {
    where: {},
    pagination: {}
  },

  getPayload: function(reducerState, params, reducer) {
    const jsonKey = toJsonKey(params);
    const state = reducerState[jsonKey];

    if (state) {
      if (state.state !== PayloadStates.FETCHING) {
        if (state.data.length === 0) {
          return _.assign({}, {
            id: undefined,
            cid: undefined,
            state: PayloadStates.NOT_FOUND,
            data: {},
            error: {}
          }, _.pick(state, ['meta', 'query']));
        }
        return _.assign({}, state.data[0], _.pick(state, ['meta', 'query']));
      }
    }

    return state;
  },

  callAction: function(action, params) {
    return action(params.where, params.pagination).payload;
  },

};