All Projects → kouhin → Redux Dataloader

kouhin / Redux Dataloader

Licence: mit
Loads async data for Redux apps focusing on preventing duplicated requests and dealing with async dependencies.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Redux Dataloader

Redux Ecosystem Links
A categorized list of Redux-related addons, libraries, and utilities
Stars: ✭ 5,076 (+3551.8%)
Mutual labels:  async, action
Redux Most
Most.js based middleware for Redux. Handle async actions with monadic streams & reactive programming.
Stars: ✭ 137 (-1.44%)
Mutual labels:  async
React Router Async Routing
react router v4 async routing
Stars: ✭ 130 (-6.47%)
Mutual labels:  async
Actix Web
Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust.
Stars: ✭ 12,723 (+9053.24%)
Mutual labels:  async
Zhttp
基于swoole的异步轻量级web框架,内部封装协程异步非阻塞全套mysql、redis、mongo、memcached连接池,可以轻松start、reload、stop,加入数据库的查询模块,框架已经封装好近乎同步写法,底层异步调用
Stars: ✭ 131 (-5.76%)
Mutual labels:  async
Github Action Markdown Link Check
Check all links in markdown files if they are alive or dead. 🔗✔️
Stars: ✭ 132 (-5.04%)
Mutual labels:  action
Lealone
极具创新的面向微服务和 OLTP/OLAP 场景的单机与分布式关系数据库
Stars: ✭ 1,802 (+1196.4%)
Mutual labels:  async
Release Drafter
Drafts your next release notes as pull requests are merged into master.
Stars: ✭ 2,119 (+1424.46%)
Mutual labels:  action
Futures Intrusive
Synchronization primitives for Futures and async/await based on intrusive collections
Stars: ✭ 137 (-1.44%)
Mutual labels:  async
Vkwave
Asynchronous framework for building high-performance & easy to scale projects interacting with VK's API.
Stars: ✭ 135 (-2.88%)
Mutual labels:  async
Figma Action
Export image assets from Figma to GitHub
Stars: ✭ 134 (-3.6%)
Mutual labels:  action
Rubico
[a]synchronous functional programming
Stars: ✭ 133 (-4.32%)
Mutual labels:  async
Nim Chronos
Chronos - An efficient library for asynchronous programming
Stars: ✭ 136 (-2.16%)
Mutual labels:  async
Spotify.py
🌐 API wrapper for Spotify 🎶
Stars: ✭ 131 (-5.76%)
Mutual labels:  async
Angular Async Loader
Load modules and components asynchronously for angular 1.x application.
Stars: ✭ 137 (-1.44%)
Mutual labels:  async
Guwen Spider
一个完整的nodeJs 串行爬虫 抓取3万多个页面。
Stars: ✭ 129 (-7.19%)
Mutual labels:  async
Pyrogram
Telegram MTProto API Client Library and Framework in Pure Python for Users and Bots
Stars: ✭ 2,252 (+1520.14%)
Mutual labels:  async
Aiohttp
Asynchronous HTTP client/server framework for asyncio and Python
Stars: ✭ 11,972 (+8512.95%)
Mutual labels:  async
Async with
The asynchronous version of Elixir's "with", resolving the dependency graph and executing the clauses in the most performant way possible!
Stars: ✭ 139 (+0%)
Mutual labels:  async
Hydro
Ultra-pure, lag-free prompt with async Git status. Designed for Fish.
Stars: ✭ 137 (-1.44%)
Mutual labels:  async

Redux Data Loader

CircleCI npm

Loads async data for Redux apps focusing on preventing duplicated requests and dealing with async dependencies.

Deeply inspired by alt Data Souces API, also inspired by redux-saga.

Instead of using redux-thunk, it handles wrapped actions and sideload async data. It also caches data requests for a while in order to prevent duplicated requests.

Installation

npm install redux-dataloader --save

Usage

1. Define actions and update the request action with load()

userActions.js

import { load } from 'redux-dataloader';

export const FETCH_USER_REQUEST = 'myapp/user/FETCH_USER/REQUEST';
export const FETCH_USER_SUCCESS = 'myapp/user/FETCH_USER/SUCCESS';
export const FETCH_USER_FAILURE = 'myapp/user/FETCH_USER/FAILURE';

export function fetchUserRequest(username) {
  // use `load` to wrap a request action, load() returns a Promise
  return load({
    type: FETCH_USER_REQUEST,
    payload: {
      username: username,
    },
  })
}

export function fetchUserSuccess(username, data) {
  // ...
}

export function fetchUserFailure(username, error) {
  // ...
}

2. Create a data loader

dataloaders.js

import { createLoader, fixedWait } from 'redux-dataloader';

import * as userActions from './userActions';

const userLoader = createLoader(userActions.FETCH_USER_REQUEST, {
  /*
   * (required) Handle fetched data, return a success action
   */
  success: (context, result) => {
    // you can get original request action from context
    const action = context.action;
    const username = action.payload.username;
    return userActions.fetchUserSuccess(username, result);
  },
  /*
   * (required) Handle error, return a failure action
   */
  error: (context, error) => {
    const action = context.action;
    const username = action.payload.username;
    return userActions.fetchUserFailure(username, error);
  },
  /*
   * (optional) By default, original request action will be dispatched. But you can still modify this process.
   */
  // loading: ({ action }) => {}
  /*
   * (required) Fetch data.
   * We use yahoo/fetchr as an example.
   */
  fetch: (context) => {
    const action = context.action;
    const username = action.payload.username;

    const fetchr = context.fetchr;
    return fetchr.read('userService')
      .params({
        username,
      }).end();
  },
  /*
   * (optional) !!! Different from alt API.
   * When shouldFetch returns false, it will prevent fetching data.
   */
  shouldFetch: (context) => {
    const action = context.action;
    const username = action.payload.username;
    const getState = context.getState;
    return !getState().user.users[username];
  }
}, {
  ttl: 10000,
  retryTimes: 3,
  retryWait: fixedWait(500),
});

export default [userLoader];

3. Register middleware

configureStore.js

import { createStore, applyMiddleware } from 'redux';
import { createDataLoaderMiddleware } from `redux-dataloader`;
import { Fetchr } from 'fetchr';
import reducer from './reducers';
import loaders from './dataloaders';

const fetcher = new Fetcher({
  xhrPath: '/api',
});

// create middleware, you can add extra arguments to data loader context
const dataLoaderMiddleware = createDataLoaderMiddleware(loaders, { fetchr });

const store = createStore(
  reducer,
  applyMiddleware(dataLoaderMiddleware)
)

// ...

4. Use it for your application

Then, just use it in your application. The following is an example that combined with redial for isomorphic use.

import { provideHooks } from 'redial';
import { fetchUserRequest } from 'userActions';
import { fetchArticleRequest } from 'articleAction';
import { fetchArticleSkinRequest } from 'articleSkinAction';

// the router location is: /:username/:articleId
// Data dependency: user <= article <= articleSkin
async function fetchData({param, dispatch, getState}) {
  try {
    // 1. Fetch user
    const username = params.username;
    await dispatch(fetchUserRequest(username)); // wait for response

    // 2. Fetch article by userId and articleId, you may use useId for authentication
    const user = getState().user.users[username];
    if (!user) {
      throw new Error(`user_not_found: ${username}`);
    }
    const articleId = params.articleId;
    await dispatch(fetchArticleRequest(user.id, articleId));

    // 3. Fetch article skin by articleId
    const article = getState().article.articles[articleId];
    if (!article) {
      throw new Error(`article_not_found: ${articleId}`);
    }
    await dispatch(fetchArticleSkinRequest(article.skinId));
  } catch (err) {
    // ...
  }
}

function mapStateToProps(state, owndProps) {
  // ...
}

@connect(mapStateToProps)
@provideHooks({
  fetch: fetchData,
})
export default class ArticleContainer extends React.Component {
  // ...
}

You can also write fetchData() with Promise:

function fetchData({param, dispatch, getState}) {
  return Promise.resolve().then(() => {
    // 1. Fetch user
    const username = params.username;
    return dispatch(fetchUserRequest(username));
  }).then(() => {
    // 2. Fetch article by userId and articleId, you may use useId for authentication
    const user = getState().user.users[username];
    if (!user) {
      throw new Error(`user_not_found: ${username}`);
    }
    const articleId = params.articleId;
    return dispatch(fetchArticleRequest(user.id, articleId));
  }).then(() => {
    // 3. Fetch article skin by articleId
    const article = getState().article.articles[articleId];
    if (!article) {
      throw new Error(`article_not_found: ${articleId}`);
    }
    return dispatch(fetchArticleSkinRequest(article.skinId));
  }).catch((err) => {
    // error handler
    // ...
  })
}

Documentation

License

MIT

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].