snowbox v1.0.5
snowbox 

Opinionated Redux abstractions for faster development.
Motivation
Most of the time, for each type of entity in your redux store, you have to implement the same actions, reducers, and selectors, over and over again. The same story holds true when it comes to calling your remote server.
Solution
Snowbox is a small collection of tools that hide the repetitiveness in your code and lets you focus on writing code that is trully important for your app. They are built on top of redux, normalizr, reselect, and immer.
Table of Contents
- Install
- Quick Start
- Api - api - get - post - put - patch - remove - request - provider - find - fetch - upsert - remove - Response - entity - actions - selectors - Hooks - Constants
- Exmples
Install
npm install snowboxQuick Start
1) Add the snowbox reducer and middleware to your store. The key where the snowbox reducer is mounted must be snowbox.
// File: app-store.js
import { createStore, combineReducers, applyMiddleware } from 'redux';
import { snowboxReducer, snowboxMiddleware } from 'snowbox';
const store = createStore(
combineReducers({
snowbox: snowboxReducer,
/* app reducers */
}),
preloadedState,
applyMiddleware(
snowboxMiddleware,
/* app middlewares */
)
);2) Configure the api and provider services.
// File: app-provider.js
import { api, provider } from 'snowbox';
import store from './app-store';
import selectAuthToken from './app-selectors';
export const appApi = api({
baseUrl: 'http://localhost:3000/api',
tokenHeader: 'auth-token',
getAuthToken: () => selectAuthToken(store.getState()), // when your token is stored in the state
});
export const appProvider = provider(api);
export default appProvider;3) Define an entity
// File: entities/todo.js
import { entity } from 'snowbox';
import appProvider from '../app-provider';
export const todoProvider = appProvider({
particle: 'todos',
});
export const todo = entity('todos', todoProvider);
export default todo;4) Build your awesome app
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetch, selectCollection } from 'snowbox';
import todo from 'entities/todo'; // Import the todo entity
import Todo from './Todo';
const todosSelector = selectCollection(todo); // Create the selector for todos
export default function MyTodos({ filter }) {
const dispatch = useDispatch();
const todos = useSelector(todosSelector); // Select your todos
useEffect(() => {
dispatch(fetch(todo)(filter)); // Request todos
}, [dispatch, fetch, todo, filter]);
return todos.map(item => <Todo key={item.id} todo={item} />);
}API
api(options)
options: object -baseUrl: string required The base url where all the api requests go (e.g.https://my.awesome.server/api). -tokenHeader: string The name of the header for the authentication token. Must be string. required whengetAuthTokenis defined. -getAuthToken: function Returns the authentication token. required whentokenHeadersi defined.
Api methods:
get(path, params)Makes a GET HTTP request and returns the response.
Params: -
path: string required Together withoptions.baseUrlit forms the destination url. -params: object The query params of the request.Returns: -
objectServer response.post(path, data = {}, params, contentType)Makes a POST HTTP request and returns the
serverResponse.Params: -
path: string required Together withoptions.baseUrlit forms the destination url. -data: object The body of the request. -params: object The query params of the request. -contentType: string The content type of the request.Returns: -
objectServer response.put(path, data = {}, params, contentType):Makes a PUT HTTP request and returns the response.
Params: -
path: string required Together withoptions.baseUrlit forms the destination url. -data: object The body of the request. -params: object The query params of the request. -contentType: string The content type of the request.Returns: -
objectServer response.patch(path, data = {}, params, contentType):Makes a PATCH HTTP request and returns the response.
Params: -
path: string required Together withoptions.baseUrlit forms the destination url. -data: object The body of the request. -params: object The query params of the request. -contentType: string The content type of the request.Returns: -
objectServer response.remove(path):Makes a DELETE HTTP request and returns the response.
Params: -
path: string required Together withoptions.baseUrlit forms the destination url.Returns: -
objectServer response.request(method, path, params, data, contentType):Makes a HTTP request and returns
serverResponse. It is the function called by all the otherapifunctions.Params: -
method: string required The HTTP method of the request. -path: string required Together withoptions.baseUrlit forms the destination url. -params: object The query params of the request. -data: object The body of the request. -contentType: string The content type of the request.Returns: -
objectServer response.
provider(api)(options)
api: object required Theapiservice that will make the HTTP requests.options: object -particle: string required The resource name in a RESTful HTTP request (e.g. thetodosinhttp://localhost:3000/api/todos/9). -idField: string The field where the unique ID for each of this entity can be found. Defaults to'id'. -entityPath: string The path where the entity data is found in nonfetchresponses. Useslodash.getbehind the scenes. Defaults to'data'. -entitiesPath: string The path where the entities data is found in thefetchresponses. Useslodash.getbehind the scenes. Defaults to'data'. -entitiesFieldName: string The field name for the entities in the result offetchrequests. Defaults to'records'. -hasMeta: boolean Whether the fetch response has metadata or not. Defaults tofalse. -metaPath: string The path where the metadata is found in thefetchresponse. Useslodash.getbehind the scenes. Defaults to''. IfmetaPathis a parent ofentitiesPath, the entities will be removed from the metadata object. -metaFieldName: string The field name for the metadata in the result offetchrequest. Defaults to'meta'. -findPath(filter, options): function Returns the HTTP path forfindrequests. Defaults to/<particle>/<filter[idField]>. The function is called with: -filter: object Thefilterpassed tofind. -options: object The provider options. -findParams(filter, options): function Returns the query params forfindrequests. Defaults to everything in thefilterobject but without the<idField>. The function is called with: -filter: object Thefilterpassed tofind. -options: object The provider options. -fetchPath(filter, options): function Returns the HTTP path forfetchrequests. Defaults to/<particle>. The function is called with: -filter: object Thefilterpassed tofetch. -options: object The provider options. -fetchParams(filter, options): function Returns the query params forfetchrequests. Defaults to everything in thefilterobject but the<idField>. The function is called with: -filter: object The filter passed tofetch. -options: object The provider options. -createMethod: string The HTTP method for create requests (when the<idField>is missing in thedatasent toupsert). It can bepost,put, orpatch. Defaults topost. -updateMethod: string The HTTP method for update requests (when the<idField>is present in thedatasent toupsert). It can bepost,put, orpatch. Defaults toput. -upsertContentType: string The content type of the create and update requests. Can be one ofsnowbox.contentTypes.JSONandsnowbox.contentTypes.FORM_DATA. When the content type isFORM_DATA, theapiwill transform thedataobject sent toupsertintoFormData. Defaults toJSON. -upsertPath(data, options): function Returns the HTTP path forupsertrequests. Defaults to/<particle>for create and/<particle>/<data[idField]>for update. The function is called with: -data: object Thedatapassed toupsert. -options: object The provider options. -upsertMethod: string The HTTP method for upsert requests. Defaults tooptions.createMethodfor create andoptions.updateMethodfor update. -removeMethod: sring The HTTP method for remove requests. It can bedelete,post,put, orpatch. Defaults todelete. -removePath(data, options): function Returns the HTTP path forremoverequests. Defaults to/<particle>/<data[idField]>. The function is called with: -data: Thedatapassed toremove. -options: object The provider options.
Provider methods:
find(filter):Calls
[GET] <api.options.baseUrl/options.findPath?options.findParamsand returnsResponse.Params: -
filter: object The filter for the requested resource.Returns: -
Responsefetch(filter):Calls
[GET] api.options.baseUrl/options.fetchPath?options.fetchParamsand returnsResponse.Params: -
filter: object The filter for the requested resources.Returns: -
Responseupsert(data, params):Calls
[options.upsertMethod] api.options.baseUrl/options.upsertPath?paramsand returnsResponse.Params: -
data: object The body of the request. -params: object The HTTP query params.Returns: -
Responseremove(data):Calls
[options.removeMethod] api.options.baseUrl/options.removePathand returnsResponse.Params: -
data: object Usually the deleted resource.Returns: -
Response
Response(response, options, isFetch)
response: object required The response object received from the server.options: object -entityPath: string The path where the entity data is found in thefindresponse. This will be the result of thefindrequest. Useslodash.getbehind the scenes. Defaults to'data'. -entitiesPath: string The path where the entities data is found in thefetchresponse. Useslodash.getbehind the scenes. Defaults to'data'. -entitiesFieldName: string The field name for the entities in the result offetchrequest. Defaults to'records'. -hasMeta: boolean Whether the fetch response has metadata or not. Defaults tofalse. -metaPath: string The path where the metadata is found in thefetchresponse. Useslodash.getbehind the scenes. Defaults to''. IfmetaPathis a parent ofentitiesPath, the entities will be removed from the metadata object. -metaFieldName: string The field name for the metadata in the result offetchrequest. Defaults to'meta'.isFetch: boolean Whether the response belongs to afetchrequest. Defaults tofalse.
Instance fields
data: anyserverResponse[options.entitiesPath]forfetchrequests andserverResponse[options.entityPath]for everything else. WhenentitiesPathorentittPathis not defined it returns theserverResponse.meta: anyserverResponse[options.metaPath]forfetchrequests whereoptions.hasMeta == trueandundefinedfor everything else.original: object Returns theserverResponse.converted: object When the request is notfetchit returnsresponse.data. When the request isfetchit returns:
{
<options.entitiesFieldName>: serverResponse[options.entitiesPath],
<options.metaFieldName>: serverResponse[options.metaPath],
}entity(key, provider, definition = {}, options = {})
key: string required The key name under which all entities of this type will be listed in the normalized response. See normalizr.provider: object A provider object that will be used to make requests to a remote server. Defaults to undefined.definition: object A definition of the nested entities found within this entity. Defaults to empty object. See normalizr.options: - all the options available for the normalizr Entity. -staleTimeout: number Amount of milliseconds that the entity will be considered fresh.fetchandfindactions won’t make remote calls to load entities resources unless fresh data is specifically requested. Defaults toundefined(i.e. all the requests are made). -singleton: boolean Whentrue, it means that there is only one entity of that type (useful for the logged user). Defaults tofalse.
actions
find(entity)(payload, meta = {}): Requests a resource from the remote server and populates the state with the result. -meta: object -refresh: boolean Force the request for fresh data even when the state is not stale. Defaults tofalse.fetch(entity)(payload, meta = {}): Requests a collection from the remote server and populates the state with the result. -meta: object -refresh: boolean Force the request for fresh data even when the state is not stale. Defaults tofalse.upsert(entity)(payload, meta = {}): Sends a create or update request to the remote server and populates the state with the result.remove(entity)(payload, meta = {}): Sends a delete request to the remote server and populates the state with the result.clearAll(payload): Clears the entire snowbox state. Useful when the user logs out.
selectors
selectOne(entity, hydrationLevels = 0, idField)(state, props): Selects the entity record that has the ID equal toprops[idField || entity.idField]. -entity: object required Anentity. -hydrationLevels: number Defines how many levels of nested entities will be denormalized. Defauls to zero. -idField: string The unique ID field name of the entity. Usually, the defaultentity.fieldIdshould be used. -state: object required Redux state. -props: object required Component props.selectCollection(entity, hydrationLevels = 0)(state, filter): Selects a collection that was requested with thefetchaction. Thefilterpassed here must match thepayloadof thefetchaction. -entity: object required Anentity. -hydrationLevels: number Defines how many levels of nested entities will be denormalized. Defauls to zero. -state: object required Redux state. -filter: object required The filter used for selecting the collection.selectAll(entity, hydrationLevels = 0)(state): Selects all the records of the entity that have been loaded on the state. -entity: object required Anentity. -hydrationLevels: number Defines how many levels of nested entities will be denormalized. Defauls to zero. -state: object required Redux state.selectMeta(entity)(state, filter): Selects themetaobject that was loaded with thefetchaction. Thefilterpassed here must match thepayloadof thefetchaction. -entity: object required Anentity. -state: object required Redux state. -filter: object required The filter used for selecting the collection.
Hooks
useList(entity, initialFilters = {}):- `entity`: _object_ **required** An `Entity`. - `initialFilters`: _object_ The initial filters for the list. Defaults to `{}`.Returns: { items, meta, status, error, prevItems, prevMeta, setFilters, upsert, remove, }
Constants
contentTypes
- `JSON`: - `FORM_DATA`actions
- `FIND` - `FETCH` - `UPSERT` - `REMOVE` - `CLEAR`statuses
- `PENDING` - `SUCCEEDED` - `FAILED`
12 months ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago