Instruction:

Create a component boilerplate:

import React, {Component} from 'react';

class PostsShow extends Component {
    render() {
        return (
            <div>
                Posts Show!
            </div>
        );
    }
}

export default PostsShow;

Import to the index.js:

import PostsShow from './components/posts_show'

And add a new route to the ReactDOM.render:

ReactDOM.render(
    <Provider store={createStoreWithMiddleware(reducers)}>
        <BrowserRouter>
            <div>
                <Switch>
                    <Route path="/posts/new" component={PostsNew}/>
                    <Route path="/posts/:id" component={PostsShow}/>
                    <Route path="/" component={PostsIndex}/>
                </Switch>
            </div>
        </BrowserRouter>
    </Provider>
    , document.querySelector('.container'));

Add new action creator:

export function fetchPost(id) {
    const request = axios.get(`${ROOT_URL}/posts/${id}${API_KEY}`);
    return{
        type: FETCH_POST,
        payload: request
    }
}

Constants:

export const FETCH_POSTS = 'fetch_posts';
export const FETCH_POST = 'fetch_post';
export const CREATE_POST = 'create_post';

Move to reducer:

import {FETCH_POSTS} from "../actions/index"
import _ from 'lodash'

export default function (state = {}, action) {
    switch (action.type) {
        case FETCH_POSTS:
            return _.mapKeys(action.payload.data, 'id');
        default:
            return state;
    }
}

Return data from reducer according to data from action:

export default function (state = {}, action) {
    switch (action.type) {
        case FETCH_POST:
            const post = action.payload.data;
            const newState = {...state};
            newState[post.id] = post;
            return newState;
        case FETCH_POSTS:
            return _.mapKeys(action.payload.data, 'id');
        default:
            return state;
    }
}

Let's refactor it in a ES6 way:

export default function (state = {}, action) {
    switch (action.type) {
        case FETCH_POST:
            // const post = action.payload.data;
            // const newState = {...state};
            // newState[post.id] = post;
            // return newState;

            // In the following code:
            //  1 - we add to state key/value pair
            //  2 - key is id
            //  3 - value is JSON object
            //  4 - we add it to the state
            return {...state, [action.payload.data.id]: action.payload.data};
        case FETCH_POSTS:
            return _.mapKeys(action.payload.data, 'id');
        default:
            return state;
    }
}

1 posts_show.js

import {connect} from 'react-redux'

2

import {fetchPost} from "../actions/index"

hook up with connect

export default connect(null, {fetchPost})(PostsShow);

componentDidMount

componentDidMount(){
    this.props.fetchPost();
}

map state to props

function mapStateToProps({posts}) {

}

retrieve a specific post by id

componentDidMount(){
    this.props.match.params.id;
    this.props.fetchPost();
}

destruct

componentDidMount(){
    const {id} = this.props.match.params;
    this.props.fetchPost(id);
}

set props and retrieve them in a reusable way.

Let's start with mapStateToProps function:

function mapStateToProps({posts}, ownProps) {
    return {post: posts[ownProps.match.params.id]};
}

After that, let's edit render function:

render() {
    const {post} = this.props;

    if(!post) {
        return <div>Loading...</div>;
    }

    return (
        <div>
            <h3>{post.title}</h3>
            <h6>Categories: {post.categories}</h6>
            <p>{post.content}</p>
        </div>
    );
}

results matching ""

    No results matching ""