Search code examples
node.jsreactjsexpressasynchronouses6-promise

why I need to refresh the page to get the new state In react Express


I have this function to add a comment to the database and then render the new comments on the page In REACT :

addComment(event) {
    event.preventDefault();
    console.log(this.state);

    axios
        /* the function of posting the comment first */
        .post('/api/comment/' + this.state.project._id ,{inputComment: this.state.inputComment})
        /* then the function of retriveng the data */
        .then(
            fetch('/api/p/' + this.state.project._id).then(res => res.json())
                .then((project) => {
                    console.log(project)
                    this.setState({ project })
                    this.setState({ inputComment: '' })
                })
        )
        .catch(err => console.log(err))
}

The problem is that I am getting the previous state before adding the last comment.

If I check the console, the function of fetching and retrieving the comments is finishing before the function of adding the comment and updating the DB, although I chained them inside then() after each other.

this is the function of posting the comment on express server which called first by axios.post():

app.post('/api/comment/:project_id', (req, res) => {
    console.log(req.body)

    mongo.connect(process.env.CONNECTION_STRING, (err, dbo) => {
        if (err) console.log('Database error: ' + err);

        let db = dbo.db('portfolio');
        let coll = db.collection('projects');
        let project_id = req.params.project_id;

        let comment = req.body.inputComment;
        db.collection('projects')
            .findOneAndUpdate({ _id: ObjectId(project_id) }, { $push: { comments: comment }  })
            .then((data) => {
                res.json({ code: 1 });
            });
    })
});

and this is the function of retrieving the data from express server which is chained after the previous one by calling fetch():

app.get('/api/p/:project_id', (req, res) => {
    mongo.connect(process.env.CONNECTION_STRING, (err, dbo) => {
        if (err) console.log('Database error: ' + err);

        let db = dbo.db('portfolio');
        let coll = db.collection('projects');
        let pproject_id = req.params.project_id;

        db.collection('projects')
            .findOne({ _id: ObjectId(pproject_id) })
            .then((data) => {
                res.json(data);
            });
    })
});

I have other functions behave the same, I need to refresh the page to get the new state.

what I have done wrong??


Solution

  • The success handler for your axios promise is a function call, so it will be immediately called and the return value will be used as the handler. Changing the block like this should give the expected result

    axios
      /* the function of posting the comment first */
      .post("/api/comment/" + this.state.project._id, {
        inputComment: this.state.inputComment
      })
      /* then the function of retriveng the data */
      .then(response =>
        fetch("/api/p/" + this.state.project._id)
          .then(res => res.json())
          .then(project => {
            console.log(project);
            this.setState({ project });
            this.setState({ inputComment: "" });
          })
      )
      .catch(err => console.log(err));