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>
);
}