Search code examples
javascriptrestbackbone.jsexpressreactjs

React + Backbone application making 2 POSTS instead of 1


I have a restful Todo List implemented with React and Backbone.

For now, I'm not talking to a database; just have an array var mytodos = []; in my server.js.
Here's the server code for POST (using Express):

app.post('/todos', function(req, res) {
    var todo = {
        id: mytodos.length,
        title: req.body.length,
        completed: req.body.completed         
    };

    mytodos.push(todo);
    console.log('POST ' + JSON.stringify(todo));
    res.send(todo);
});

When I add an item to the list, I see two POSTS being made for some reason.

POST: {"id":0,"title":"test","completed":false}
POST: {"id":1,"title":"test","completed":false}

In Chrome Dev. Mode, I see:

PUT localhost/todos/0 404 (Not Found)
PUT localhost/todos/1 404 (Not Found)

Two PUT requests!

Trying to reason through it - save() is called which calls sync(). Since the model doesn't have an id yet (only cid), it make a POST request and a todo (id = 0) is added to mytodos which then updates the model on the client (adds the id attribute). Since a change was detected, it does another save() which PUTS it to the server (<-- may very well be wrong here; not sure if the updated model would cause a PUT).

This might explain the PUT, but not the double POST.

Here is where save() is getting called (under TodoApp = React.createClass...:

componentDidUpdate: function() {
    this.props.todos.forEach(function(todo) {
        console.log('componentDidUpdate: ' + todo.id); // logs: undefined, 0, 1
        todo.save();
    });
},
...
save: function(todo, text) {
    console.log('Save: ' + todo.id); // only logged on update
    todo.save({title: text});
    this.setState({editing: null});
},
...
}

Why does this happen?
Why is it PUTting in addition to POSTing? And why is it doing it twice?

Edit:

I resolved the double POST by changing create to add - reference to where I got help.

The last problem is a PUT 404 (Not Found) for an item that is definitely on the server. Interestingly, the PUT is not going through my server it seems. My server only logs the POST. The PUT is being logged somewhere else.


Solution

  • I resolved the double POST by changing create to add

    More specifically a certain event was triggering a Backbone.Collection.create call which according to this syncs with the server.

    In my React code, I have a componentDidUpdate which calls Backbone.Model.save which also tries sending to the server. Here.

    Because the event caused both create and save to be executed, POST was firing twice.