0

I keep getting a typeerror: cannot read property ... I'm setting the state to a JSON object from a fetch response. The String and Date properties of the object seem to be rendering fine but the Array and Number properties keep getting type errors.

class ViewPost extends Component {
    state = {
      post: {}
    }

    constructor(props) {
      super(props);
      this.setPostState = this.setPostState.bind(this);
    }

    componentWillMount() {
      this.setPostState();
    }

    setPostState() {
      let postTitle = this.props.match.params.id;
      fetch('/posts/getpost', {
        method: 'post',
        headers: {
          'Accept': 'application/json, text/plain, */*',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          title: postTitle
        })
      })
      .then(res => res.json())
      .then(post => this.setState({ post }))
    }

    render() {
      return (
        <div className="Post">
          <div className="card">
            <img className="img-fluid" src="/img/darkstockphoto.jpg" alt="Post"/>
            <div className="card-body">
              <h4 className="card-title">{this.state.post.title}</h4>
              <p className="card-text">{this.state.post.author}</p>
              <p className="card-text">{this.state.post.date}</p>
              <p className="card-text">{this.state.post.body}</p>
            </div>
          </div>
          <hr />
          {this.state.post.comments && this.state.post.comments.map(comment => (
            <div key={comment.author + comment.date} className="card card-body">
              <h4 className="card-title">{comment.title}</h4>
            </div>
          ))}
        </div>
     );
   }
}

export default ViewPost;
itsame-ebp
  • 63
  • 1
  • 1
  • 4
  • See this answer https://stackoverflow.com/questions/47027035/why-is-my-react-component-this-state-updateclothing-saying-undefined-even-thou/47028520#47028520. also since this.state.post is empty initially it makes sense to also render `this.state.post.title` and other things also conditionally like you are doing for comments – Shubham Khatri Oct 31 '17 at 06:37

1 Answers1

3

setState is asynchronous, so you need to handle your this.state.post like this:

render() {

  if (this.state.post) {
    return (<div className="Post">
      <div className="card">
        <img className="img-fluid" src="/img/darkstockphoto.jpg" alt="Post"/>
        <div className="card-body">
          <h4 className="card-title">{this.state.post.title}</h4>
          <p className="card-text">{this.state.post.author}</p>
          <p className="card-text">{this.state.post.date}</p>
          <p className="card-text">{this.state.post.body}</p>
        </div>
      </div>
      <hr/> {
        this.state.post.comments && this.state.post.comments.map(comment => (<div key={comment.author + comment.date} className="card card-body">
          <h4 className="card-title">{comment.title}</h4>
        </div>))
      }
    </div>);
  }

  return null;
}
Syed
  • 269
  • 2
  • 8