.
-, , . , , .
, redux-dataloader '.
import { load } from 'redux-dataloader'
function fetchPostsRequest() {
return load({
type: 'FETCH_POSTS'
});
}
function fetchPostsSuccess(posts) {
return {
type: 'LOADED_POSTS',
posts: posts
};
}
function fetchCommentsRequest(postId) {
return load({
type: 'FETCH_COMMENTS',
postId: postId
});
}
function fetchCommentsSuccess(postId, comments) {
return {
type: 'LOADED_COMMENTS_OF_POST',
postId: postId,
comments: comments
}
}
"FETCH_POSTS" "FETCH_COMMENTS":
import { createLoader, fixedWait } from 'redux-dataloader';
const postsLoader = createLoader('FETCH_POSTS', {
success: (ctx, data) => {
const { postId } = ctx.action;
return fetchPostsSuccess(data);
},
error: (ctx, errData) => {
},
shouldFetch: (ctx) => {
},
fetch: async (ctx) => {
}
});
const commentsLoader = createLoader('FETCH_COMMENTS', {
success: (ctx, data) => {
const { postId } = ctx.action;
return fetchCommentsSuccess(postId, data);
},
error: (ctx, errData) => {
},
shouldFetch: (ctx) => {
const { postId } = ctx.action;
return !!ctx.getState().comments.comments[postId];
},
fetch: async (ctx) => {
const { postId } = ctx.action;
},
}, {
ttl: 10000,
retryTimes: 3,
retryWait: fixedWait(1000),
});
export default [
postsLoader,
commentsLoader
];
decux-dataloader redux
import { createDataLoaderMiddleware } from 'redux-dataloader';
import loaders from './dataloaders';
import rootReducer from './reducers/index';
import { createStore, applyMiddleware } from 'redux';
function configureStore() {
const dataLoaderMiddleware = createDataLoaderMiddleware(loaders, {
});
return createStore(
rootReducer,
applyMiddleware(dataLoaderMiddleware)
);
}
OK, (requestAction) .
class PostContainer extends React.Component {
componentDidMount() {
const dispatch = this.props.dispatch;
const getState = this.props.getState;
dispatch(fetchPostsRequest()).then(() => {
const postPromises = getState().posts.posts.map(post => {
return dispatch(fetchCommentsRequest(post.id));
});
return Promise.all(postPromises);
}).then() => {
});
}
render() {
}
}
export default connect(
state => ()
)(PostContainer);
NOTICE Promised query action with caching in ttl and preventing duplicate requests.
By the way, if you use async / await, you can handle data retrieval using the dataloader reducer as follows:
async function fetchData(props, store) {
try {
const { dispatch, getState } = store;
await dispatch(fetchUserRequest(props.userId));
const userId = getState().users.user.id;
await dispatch(fetchPostsRequest(userId));
const posts = getState().posts.userPosts[userId];
const commentRequests = posts.map(post => fetchCommentsRequest(post.id))
await Promise.all(commentRequests);
} catch (err) {
}
}