Example

This is an example how the library works together. It is a pretty simple example; if you need something more specific, please go to examples, or for some specific parts to the API part. We will build a simple store to fetch documents, and after we fetch them, we will show notifications for 5 seconds, and then close it.

import { createEntities, createTile, createSyncTile, createMiddleware } from 'redux-tiles';
import { createStore, applyMiddleware } from 'redux';
import { sleep } from 'delounce';
import api from '../api';

// async tile, which will query the api, and will automatically populate
// isPending while it is processing, and put result to `data` or `error`
// field, depending how promise will be resolved
const documents = createTile({
  type: ['documents', 'api'],
  fn: ({ api, params }) => api.fetch(`/documents/${params.type}`),
  // we nest documents by type, so requests for different types
  // are independent
  nesting: ({ type }) => [type],
});

// sync tile, which does not perform any async operations. in fact, we
// still can dispatch async actions, but we are not allowed to wait for
// them – result from this function will be put under corresponding state
const notifications = createSyncTile({
  type: ['ui', 'notifications'],
  fn: ({ params }) => params.data,
  nesting: ({ type }) => [type],
});

// this tile will be async, but it won't perform direct api requests
// instead, it will dispatch other tiles; redux-tiles encourages you
// to separate your logic to small parts, so it is easy to combine it
// and replace/remove parts later
const fetchDocumentWithNotification = createTile({
  type: ['documents', 'fetchWithNotification'],
  fn: async ({ dispatch, actions, params: { type } = {} }) => {
    // we dispatch other tile, instead of downloading
    // document right here – it allows us to compose
    // small parts of our logic much easier
    await dispatch(actions.api.documents({ type }));
    const data = `Document ${type} was downloaded!`;
    dispatch(actions.ui.notifications({ type, data }));

    await sleep(params.timeout || 5000);
    // sending type without data we will close notification
    dispatch(actions.ui.notifications({ type: params.type }));

    return { ourData: 'some' };
  },
  nesting: ({ type }) => [type],
});

const tiles = [documents, notifications, fetchDocumentWithNotification];

const { acttons, reducer, selectors } = createEntities(tiles);
const { middleware, waitTiles } = createMiddleware({ actions, selectors });
const store = createStore(reducer, applyMiddleware(middleware));

// we dispatch only the most complicated action – this tile is the "essense" of
// the application, and it only composes other tiles, which have their own
// single responsibility – fetch documents and show notifications
store.dispatch(actions.documents.fetchWithNotification({ type: 'terms' }));

// this function will wait all dispatched actions, which can be helpful in
// server-side rendering, to wait all requests
await waitTiles();
// let's dispatch another notification, to take a look 
store.dispatch(actions.ui.notifications({ type: 'agreement', data: 'Our agreement!' }));

// let's print our final store
console.log(JSON.stringify(store.getState(), null, 2));
/*

{
  documents: {
    api: {
      terms: {
        isPending: false,
        fetched: true,
        data: {
          url: 'https://example.com/terms.pdf',
          size: 512
        },
        error: null,
      },
    },
    fetchWithNotification: {
      terms: {
        isPending: false,
        fetched: true,
        data: { ourData: 'some' },
        error: null,
      },
    },
  },
  ui: {
    notifications: {
      terms: undefined,
      agreement: 'Our agreement!',
    },
  },
}
*/

results matching ""

    No results matching ""