I've done a tutorial on setting up dynamic nested routes using posts as an example. However, the example only showed how to use :id in the url, I want to be able to use :title from my database instead.
So right now I am able to get this url when I click on an item from the list of posts from /posts: '/posts/1' which comes from '/posts/:id'.
However, I want to be able to show '/posts/ramen' in the url when the ramen post is selected. I tried changing the 'id' to 'title' for the 'this.props.history.push' but this seems to affect the way that FullPost.js uses that id to pick up the correct path for the data retrieval via Axios.
Below is my code:
My data is set up like this: posts.json
posts:
0:
title: "ramen"
id: 1
1:
title: "udon"
id: 2
2:
title: "sushi"
id: 3`
Posts.js: This is a list of posts, where each post is selectable
import React, { Component } from 'react';
import axios from '../../../axiosPosts';
import Aux from '../../../hoc/Aux/Aux';
import classes from './Posts.css';
import Post from '../../../components/Post/Post';
class Posts extends Component {
state = {
posts: []
}
componentDidMount () {
this.getData(this.props.pathname, this.props.filter);
}
getData(pathname, filter) {
axios.get(pathname + '.json')
.then(response => {
const post = response.data.filter(({category}) => category === filter);
const updatedPosts = post.map(post => {
return {
...post
}
});
this.setState({
posts: updatedPosts
});
})
.catch(error => {
console.log(error);
});
}
postSelectedHandler = ( id ) => {
this.props.history.push( this.props.match.url + '/' + id );
}
render () {
let posts = <p style={{textAlign: 'center'}}>Whoops! Something went wrong.</p>;
if(!this.state.error) {
posts = this.state.posts.map(post => {
return (
<Post
key={post.id}
title={post.title}
clicked={() => this.postSelectedHandler( post.id )} />
);
});
};
return (
<Aux>
<div className={classes.PostList}>
<h2 className={classes.PostListTitle}>{this.props.filter}</h2>
{posts}
</div>
</Aux>
)
}
}
export default Posts;
FullPost.js - This is the page that loads up when a post is selected
import React, { Component } from 'react';
import axios from '../../../axiosPosts';
import classes from './FullPost.css';
class FullPost extends Component {
state = {
loadedPost: null
}
componentDidMount () {
this.loadData();
}
loadData() {
if ( this.props.match.params.id ) {
if ( !this.state.loadedPost || (this.state.loadedPost && this.state.loadedPost.id !== +this.props.match.params.id) ) {
axios.get( '/posts/' + (this.props.match.params.id - 1) + '.json' )
.then( response => {
this.setState( { loadedPost: response.data } );
} );
}
}
}
render () {
let post = <p style={{ textAlign: 'center' }}>Please select a Post!</p>;
if ( this.props.match.params.id ) {
post = <p style={{ textAlign: 'center' }}>Loading...!</p>;
}
if ( this.state.loadedPost ) {
post = (
<div className={classes.FullPost}>
Content
</div>
);
}
return post;
}
}
export default FullPost;