TODO với React + Rails Part 8: Realtime with Actioncable
Bài đăng này đã không được cập nhật trong 5 năm
Trong những bài trước mình đã làm xong TODO App với chức năng cơ bản nhất như Add, Update, Delete, Done, ... Hôm này mình sẽ implement thêm chức năng realtime cho những thao tác đó. Như các bạn đã biết từ Rails 5 trở lên thì đã có hỗ trợ sẵn actioncable để làm realtime cho project Rails của mình.
Implement phía Server
Đầu tiên, generate channel:
rails generate channel Tasks
Nó sẽ tạo những files sau đây:
      create  app/channels/tasks_channel.rb
   identical  app/assets/javascripts/cable.js
      create  app/assets/javascripts/channels/tasks.coffee
Trong file app/channels/tasks_channel.rb
# app/channels/tasks_channel.rb
class TasksChannel < ApplicationCable::Channel
  def subscribed
    stream_from "tasks_channel"
  end
  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end
Ở đây mình sẽ subscribed vào channel có tên là tasks_channel. Những data broadcast đến channel này sẽ nhận được.
Tiêp theo ở trong controller mình sẽ broadcast đến channel tasks_channel với data cần thiết như sau:
  def create
    task = Task.create! task_params
    ActionCable.server.broadcast("tasks_channel",
      {type: "add", task: Api::V1::TaskSerializer.new(task)})
    render json: {
      success: true,
      data: Api::V1::TaskSerializer.new(task)
    }
  end
  
  def update
    task = Task.find params[:id]
    task.update_attributes! task_params
    ActionCable.server.broadcast("tasks_channel",
      {type: "update", task: Api::V1::TaskSerializer.new(task)})
    render json: {
      success: true,
      data: Api::V1::TaskSerializer.new(task)
    }
  end
  
   def destroy
    task = Task.find params[:id]
    ActionCable.server.broadcast("tasks_channel",
      {type: "delete", task: Api::V1::TaskSerializer.new(task)})
    task.destroy!
    render json: {
      success: true
    }
  end
Mỗi action đều có type dùng để bên client biết được là data received là từ những action nào.
Implement phía Client
Actioncable không chỉ support cho bên server, nó cũng có support cho Reactjs.
yarn add actioncable
Phía Client, chúng ta sẽ cần 3 bước chính như sau:
- Kết nối đến ‘/cable’
 - Subscribe tới channel 'tasks_channel'
 - Lắng nghe để nhận data
 
Trong file src/TodoList.js, trong componentDidMount modify code như sau:
  componentDidMount() {
    ...
    const cable = ActionCable.createConsumer('ws://192.168.2.103:2000/cable'); // Kết nói
    this.subscriptions = cable.subscriptions.create('TasksChannel', { // subscribe
      received: (data) => { // data nhận được
        if(data.type === 'add') {
          this.setState({items: [...this.state.items, data.task]});
        } else if(data.type === 'update') {
          let updatedData = this.state.items.map(item => {
            if(item.id === data.task.id) {
              return {...data.task}
            }
            return item;
          });
          this.setState({
            items: updatedData
          })
        } else if(data.type === 'delete') {
          const filteredItems = this.state.items.filter(item => {
            return item.id !== data.task.id
          })
          this.setState({
            items: filteredItems
          })
        }
      }
     })
  }
Đến đây là đã xong. =))
Kết quả:

Để hiểu chi tiết về actioncable, bạn hãy vào document của nó xem nhé.
All rights reserved