Sylar
Sylar

Reputation: 12092

Get live updated data with ajax in a react component

Story:

User clicks "add", it sets a value in the database to true. Clicks "remove", updates same column to false in the database:

def add
  u = User.find(1)
  u.foo = true
  u.save
  u.reload
  head :ok
end

def remove
  u = User.find(1)
  u.foo = false
  u.save
  u.reload
  head :ok
end

React button component:

...

_add(){
  $.ajax({
    url: ''url-to-the-controller-action-(add),
    type: 'POST',
    success: function (data) {
        console.log("DB is set to: " this.props.uid)
    },
    error: function (data) {
        console.log("not added")
    }
  });
},

_remove(){
  $.ajax({
    url: ''url-to-the-controller-action-(remove),
    type: 'POST',
    success: function (data) {
        console.log("DB is set to: " this.props.uid) 
    },
    error: function (data) {
        console.log("not removed")
    }
  });
},

render(){
  return(
    <div>
      <button onClick={this._add}>add</button>
      <button onClick={this._remove}>remove</button>
    </div>
  )
}

...

My button receives props from another component:

Foo component

getInitialState: function() {
  return{
    uid: this.props.data,

  }
}

Foo's render:

<Button uid={this.state.uid} />

I am sure I can achieve this without the need for flux/redux as that would be an over kill for this tiny component. I have looked into this but not sure how to use it.

The app works but I have to refresh the page to see the changes.

Or, Rails 5 is my best option with action cable?

Upvotes: 0

Views: 1627

Answers (1)

Florent Ferry
Florent Ferry

Reputation: 1387

On success, you need to inform Foo component than uid has changed.

In Foo component:

onChange: (uid) ->
   this.setState({uid: uid})

render: ->
  <Button uid={this.state.uid} onChange={this.onChange}/>

In Button component:

_add(){
  $.ajax({
    url: ''url-to-the-controller-action-(add),
    type: 'POST',
    success: function (data) {
     this.props.onChange(data["uid"])
     console.log("DB is set to:", data["uid"])
    },
    error: function (data) {
       console.log("not added")
    }
  });
},

In your action:

def add
  ...
  render json: { uid: u.foo }
end

On why you need refresh here:

When you make your ajax call, data are updated in database. But on your success callback, you need to update your view with new data. When you log this.props.uid, you log old data in memory, and when you hit refresh, data are replaced by fresh data from database.

In jQuery for example, you need to replace your element in DOM with fresh data passed in success callback. In ReactJS, you need to update the state to re-render the component.

Here, your component Button is a child of Foo, and receive uid like props. So you need to inform your parent component than uid has changed to update state, and re-render itself, and his childs.

Upvotes: 3

Related Questions