1
votes

From an array of posts that are passed and rendered to one component, I want to be able to render a single post of this array into another component but I can't find a way to do this.

I have two components that I use for this case, the first component "Blog" renders a preview of all the posts that are in the array. Each post has a<Link to={/blog/post-1/:${post.id}}>Go to post</Link> to the second component "Post" which renders a single post from the array. I am using react boiler plate for this.

First my container who has a dummy array of posts:

import React from 'react';
// other imported stuff
import Blog from 'components/Blog';

class BlogPage extends React.Component {

render() {
// dummy posts data
const posts = [
  {
    id: 1,
    title: 'How to Cook Blue Meth',
    description: 'Lorem ipsum dolor sit amet, turpis at',
    thump: 'thump.jpg',
    hero: '/img/',
    category: 'k1',
    fullname: 'Walter White',
    published: '10.05.2016, 15:30pm',
  },
  {
    id: 2,
    title: 'Passenger',
    description: 'Lorem ipsum dolor sit amet, turpis at',
    thump: 'thump.jpg',
    hero: '/img/',
    category: 'k2',
    fullname: 'Chino Moreno',
    published: '10.05.2016, 15:30pm',
  },
  // and more posts...
];
return (
// this is the first component
   <div>
     <Blog posts={posts} />
   </div>
   );
  }
}
export default connect(null, mapDispatchToProps)(BlogPage);

Here is the first component Blog:

import React from 'react';
import { Link } from 'react-router';

class Blog extends React.Component {

renderPosts() {
  return (
    <ul>
      {this.props.posts.map((post, idx) => {
        return (
          <li key={idx}>
            <p>{post.title}</p>
            <p>{post.category}</p>
            <p>{post.thump}</p>
            <p>{post.fullname}</p>
            <p>{post.published}</p>
            <Link to={`/blog/post-1/:${post.id}`}>Go to post </Link>
          </li>
         );
       })}
    </ul>
   );
}
render() {
  return (
    <div>
      {this.renderPosts()}
    </div>
  );
 }
}
Blog.propTypes = {
  props: React.PropTypes.array,
};
export default Blog;

And the second component Post:

import React from 'react';

class Post extends React.Component {

render() {
  return (
     <div>
       <p>{this.props.post.hero}</p>
       <p>Title:{this.props.post.title}</p>
       <p>{this.props.post.description}</p>
       <p>Category:{this.props.post.category}</p>
       <p>{this.props.post.thump}</p>
       <p>Author:{this.props.post.fullname}</p>
       <p>Published:{this.props.post.published}</p>
     </div>
  );
 }
}
Post.propTypes = {
  post: React.PropTypes.object,
};
export default Post;

I import this second component into another container:

import React from 'react';
import Post from 'components/Blog/Post';

class PostPage extends React.Component {

 render() {
    return (
     <div>
       <Post post={post} />
     </div>
    );
 }
}
export default connect(null, mapDispatchToProps)(PostPage);

This are my routes:

{
  path: '/blog',
  name: 'blog',
  getComponent(nextState, cb) {
    System.import('containers/BlogPage')
      .then(loadModule(cb))
      .catch(errorLoading);
  },
},
{
  path: '/blog/post-1/:id',
  name: 'blog-post-1',
  getComponent(nextState, cb) {
    System.import('containers/BlogPage/PostPage')
      .then(loadModule(cb))
      .catch(errorLoading);
  },
},

I just added this routes to the routes.js in the react boiler plate. In this point I don't know how to pass the single post to get rendered. Any help would be appreciated

1
Who is the parent container of PostPage ?azium
Hey, quick comment: never use indices as your React key! React uses the key prop to figure out how to shift things around when items are removed or added, and indices are not unique. You need to use something else as your key prop.ffxsam
BlogPage is the parent.Marco Chavez
I can't really understand what the question is. If you want to render a single post, doesn't <Post post={post} /> do the trick?ffxsam
Oh ok you didn't have that in your code.. so your BlogPage is parent to both Blog and PostPage? I think you should show your route config as well.... because you can get the current post from your posts array via this.props.paramsazium

1 Answers

2
votes

First you need to define the data in the reducer, that way you will be able to send it to any page that you want.

In this case I would recommend you to create two folders inside the containers folder, one for the lists of post and one for the single post.

You will need to define a reducer to store the list of posts (instead of defining the list in the component itself), take a look at the code already in the boiler plate: https://github.com/mxstbr/react-boilerplate/blob/master/app/containers/HomePage/reducer.js

Then you need to connect the reducer with the component and map the redux state with the component props, like this: https://github.com/mxstbr/react-boilerplate/blob/master/app/containers/HomePage/index.js#L139

Finally you would use those props to render the list, basically using this.props.posts on your BlogPage component, something similar to this: https://github.com/mxstbr/react-boilerplate/blob/master/app/containers/HomePage/index.js#L76

Once you have the list renderer you will need to create the PostPage component in a different folder, then connect the reducer that contains the data and get the item from the ID you are receiving in the URL param, (usually instead of that you would request to the server the data, but for the sake of simplicity just get the post from the existing reducer).

The idea here is to use redux to manage the data, that way you will be able to send data to any component, using the connect and mapping the state to the props.

PS: Don't forget to inject your reducer when defining the route: https://github.com/mxstbr/react-boilerplate/blob/master/app/routes.js#L33 this is a very important step ;)