kouhin / Redux Dataloader
Licence: mit
Loads async data for Redux apps focusing on preventing duplicated requests and dealing with async dependencies.
Stars: ✭ 139
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
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
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
Nim Chronos
Chronos - An efficient library for asynchronous programming
Stars: ✭ 136 (-2.16%)
Mutual labels: async
Angular Async Loader
Load modules and components asynchronously for angular 1.x application.
Stars: ✭ 137 (-1.44%)
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
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].