Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React componentDidMount not updating the state

I have a react component which starts with a blank default state in the constructor method. When the componentDidMount I want to update the state with stuff which I get from my API via AJAX.

The code for this component looks as following :

import React from 'react';
import Header from './Header';
import FeedOwnerColumn from './FeedOwnerColumn';
import FeedColumnRight from './FeedColumnRight';
import ReportBug from './ReportBug';

class FeedApp extends React.Component{
  constructor(){
    super();

    this.addComment = this.addComment.bind(this);
    this.componentDidMount = this.componentDidMount.bind(this);

    this.state = {
      ownerInfo:{},
      ownerDogs:[],
      ownerApps:[],
      ownerChat:{},
      posts:[]
    }
  }
  componentDidMount(e){
    var that = this;
    $.get('/api/getUserInit', function(result) {
      console.log(result);
      this.setState({
        ownerInfo: result.ownerInfo,
        ownerDogs: result.ownerDogs,
        ownerNotifications: result.ownerNotifications,
        ownerChat: result.ownerChat,
        posts: result.posts
      });
    }.bind(this));
  }
  addComment(e){
    e.preventDefault();
    var currTime = new Date();
    currTime = currTime.toLocaleString();  
    var commentContent = e.target.childNodes[0].value; 
    var key = Math.random();
    key = Math.round(key);    
    var newComment = {
      id: key,
      name: "Peter Paprika",
      date: currTime,
      thumb_picture:"/imgs/user-q.jpg",
      profile_link: "/user/123",
      content: commentContent,
      like_amount: 0
    };  
    var postsObj = this.state.posts;
    //console.log(postsObj[0].comments);   
    var newComments = postsObj[0].comments;
    newComments.push(newComment); 
    console.log(newComments);
    this.setState({posts: postsObj}); 
  }
  render() {
    return (
        <div className="clearfix wrapper">
          <Header />
          <FeedOwnerColumn />
          <FeedColumnRight posts={this.state.posts} addComment={this.addComment} />
          <ReportBug />
        </div>
    );
  }
}


export default FeedApp;

Unfortunately the this.setState({}) in the componentDidMount method doesn't seem to get called correctly since there is no state update happening and my map functions which expect an array have nothing to do and return an error.

The object which I want to use in the state update looks like this:

ownerChat: Object
ownerDogs: Array[1]
ownerInfo: Object
ownerNotifications: Array[0]
posts: Array[2]

I don't really know what else to try beside this method :/

like image 322
noa-dev Avatar asked Sep 27 '22 02:09

noa-dev


1 Answers

If I understand correctly, you want to rerender the mounting code when you update the state. ComponentDidMount will only fire on the initialization of the component. All updates are fired through ComponentDidUpdate. Use that interface for anything that is going to happen when the state is updated.

componentDidUpdate: function (prevProps, prevState) {
...
}

UPDATE

Sorry, I was using my phone to answer this question and I think I didn't read it right. You would use componentDidUpdate if you wanted to make the ajax call every time a change occurred to state, which is not what you are asking.

I noticed you are redeclaring the componentDidMount in your constructor, that shouldn't be there as it is already declared and you are overwriting it. Other than that piece of code I do not see anything wrong here. componentDidMount should fire away and update correctly. However, I am reading that your map functions are erroring when the objects are empty. Make sure you are handling an empty state because your first bind will be empty and then the second bind will have data. The error in your mapping might be the culprit here. This example prevents the children from being bound until the ajax call returns.

import React from 'react';
import Header from './Header';
import FeedOwnerColumn from './FeedOwnerColumn';
import FeedColumnRight from './FeedColumnRight';
import ReportBug from './ReportBug';

class FeedApp extends React.Component{
  constructor(){
    super();

    // only adding functions not defined by super
    this.addComment = this.addComment.bind(this);

    this.state = {
      hasData: false,
      ownerInfo:{},
      ownerDogs:[],
      ownerApps:[],
      ownerChat:{},
      posts:[]
    }
  }
  componentDidMount(e){
    var that = this;
    $.get('/api/getUserInit', function(result) {
      console.log(result);
      console.log('isMounted: ' + this.isMounted());
      if (this.isMounted()) {
        this.setState({
            hasData: true,
            ownerInfo: result.ownerInfo,
            ownerDogs: result.ownerDogs,
            ownerNotifications: result.ownerNotifications,
            ownerChat: result.ownerChat,
            posts: result.posts
        });
      }
    }.bind(this));
  }
  addComment(e){
    e.preventDefault();
    var currTime = new Date();
    currTime = currTime.toLocaleString();  
    var commentContent = e.target.childNodes[0].value; 
    var key = Math.random();
    key = Math.round(key);    
    var newComment = {
      id: key,
      name: "Peter Paprika",
      date: currTime,
      thumb_picture:"/imgs/user-q.jpg",
      profile_link: "/user/123",
      content: commentContent,
      like_amount: 0
    };  
    var postsObj = this.state.posts;
    //console.log(postsObj[0].comments);   
    var newComments = postsObj[0].comments;
    newComments.push(newComment); 
    console.log(newComments);
    this.setState({posts: postsObj}); 
  }
  render() {
    var content = '';
    if (this.state.hasData) {
        content = ( 
          <div>
             <Header />
             <FeedOwnerColumn />
             <FeedColumnRight posts={this.state.posts} addComment={this.addComment} />
             <ReportBug />
          </div>
         );
    }
    return (
        <div className="clearfix wrapper">
            {{ content }}
        </div>
    );
  }
}


export default FeedApp;

Let me know if this works for you.

like image 116
Victoria French Avatar answered Oct 11 '22 18:10

Victoria French