Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Requesting resource from API server

Tags:

reactjs

redux

In a very conventional pattern, you have a list of posts at /posts and a detail view at /posts/1. If you have an API server on the backend and React+Redux on the frontend, you probably fetch resources when you reach /posts. But what do you do when you reach /posts/1? If you landed /posts/ first, you already have all the resources, so you can maybe do the following:

  1. Have posts reducer that returns all the posts we fetched from API server
  2. Have currentPost reducer that returns only the relevant post

To set currentPost you can dispatch an action that updates currentPost as soon as you click a post in the index view.

But if you landed /posts/1 without going to the index page, or refreshed /posts/1, you don't have the resources that you load in the index page (i.e. posts reducer returns []). To solve this, you can request /posts/1 from the API server and set currentPost then.

Question: Did I understand the flow correctly? I am not sure if currentPost reducer is even necessary. Also, I am not sure if it's conventional to use the resources from the index page and request a single resource only when it's necessary.

like image 207
Maximus S Avatar asked Feb 01 '26 11:02

Maximus S


1 Answers

If you get all data you need to display currentPost in /posts request, will be sufficient to have one reducer to avoid duplicating items.

In postsReducer you need to handle two actions:
1. When you get all posts from server, your reducer should return them.
2. When you get a particular post, just append him to all posts list and return resulting array.

//reducers.js
function postsReducer(state = [], action) {
    switch (action.type) {
        case 'RECEIVE_POSTS':
            return action.posts;
        case 'RECEIVE_POST':
            return [...state, action.post]
        default:
            return state;
    }
}

PostContainer should dispatch an action to fetch currentPost. When currentPost post data will be fetched from server, you can pass it to your Post presentational component.

// PostContainer.js
class PostContainer extends Component {
    componentWillMount() {
        if (!this.props.post) {
            this.props.dispatch(loadPost(this.props.params.id));
        };
    }
    render() {
        return (
            <Post post={this.props.post}
        );
    }
}
function mapStateToProps(state, ownProps) {
    // if you're using react-router, post id will be in `params` property.
    const id = ownProps.params.id;
    return {
        post: state.posts.filter(post => post.id === id)[0]
    };
};
export default connect(mapStateToProps)(PostContainer);

PostsListContainer should dispatch action to fetch all posts from server. When request finished successfully, you will pass array with posts to PostsList component.

// PostsListContainer.js
class PostsListContainer extends Component {
    componentWillMount() {
        if (!this.props.posts) {
            this.props.dispatch(loadPosts());
        }
    }
    render() {
        return (
            <PostsList posts={this.props.posts}
        );
    }
}
function mapStateToProps(state) {
    return {
        posts: state.posts
    }
};
export default connect(mapStateToProps)(PostsListContainer);
like image 135
1ven Avatar answered Feb 03 '26 06:02

1ven