【问题标题】:Cannot access data from ActionCable on React front-end无法从 React 前端的 ActionCable 访问数据
【发布时间】:2019-08-12 11:07:24
【问题描述】:

我正在尝试使用 actioncable 从 rails 后端广播属于某个游戏的消息。

在我的messages_controller中:

  def create
@game = Game.find(message_params[:game_id])
@message = Message.new(message_params)
if @message.save
  serialized_data = ActiveModelSerializers::Adapter::Json.new(
    MessageSerializer.new(@message)
  ).serializable_hash
  MessagesChannel.broadcast_to @game, serialized_data
  head :ok
end
end

在我的messages_channel中:

  def subscribed
    @game = Game.find(params[:id][:game_id])
    stream_from @game
  end

在前端,我使用的是这个文件:

import ActionCable from 'actioncable';
import { CABLE } from "../constants";

export default function MessagesSubscription(
  game_id,
  { onUpdate = () => {} } = {}
) {
  // 2. Define our constructor
  this.cable = ActionCable.createConsumer(CABLE);
  // this.channel;
  this.game_id = game_id;
  this.onUpdate = onUpdate;

  // 3. Define the function we will call to subscribe to our channel
  this.subscribe = () => {
    console.log("subscribed")
    this.channel = this.cable.subscriptions.create(
      { channel: 'MessagesChannel', id: this.game_id },
      {
        connected: this.connected,
        disconnected: this.disconnected,
        received: this.received,
        rejected: this.rejected,
      }
    );
  };

  // 4. Define our default ActionCable callbacks.
  this.received = (data) => {
    console.log(`Received Data: ${data}`);

    this.onUpdate(data);
  };

  this.connected = () => {
    console.log(`this.connected`);
  };

  this.disconnected = () => {
    console.warn(`this.disconnected.`);
  };

  this.rejected = () => {
    console.warn('I was rejected! :(');
  };
}

问题是在客户端我可以点击连接、断开和拒绝,但我不能点击接收。

在运行服务器和客户端时,如果我查看终端中的 rails 后端,我会看到以下内容:

MessagesChannel 正在传输订阅确认 MessagesChannel 正在从 #Started 流式传输 在 2019-03-21 10:29:09 -0400 开始获取 127.0.0.1 的“/api/v1/cable” GET "/api/v1/cable/" [WebSocket] for 127.0.0.1 at 2019-03-21 10:29:09 -0400 成功升级到 WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: Upgrade, HTTP_UPGRADE: websocket) 无法执行 命令来自 ({"command"=>"subscribe", "标识符"=>"{\"频道\":\"MessagesChannel\",\"game_id\":\"15\"}"}) [NoMethodError - 未定义的方法[]' for nil:NilClass]: /Users/flatironschool/Development/code/Flatiron/mod5/project/deep_forest_api/app/channels/messages_channel.rb:3:in subscribed' | /Users/flatironschool/.rvm/gems/ruby-2.6.1/gems/actioncable-5.2.2.1/lib/action_cable/channel/base.rb:179:in block in subscribe_to_channel' | /Users/flatironschool/.rvm/gems/ruby-2.6.1/gems/activesupport-5.2.2.1/lib/active_support/callbacks.rb:109:in block in run_callbacks' | /Users/flatironschool/.rvm/gems/ruby-2.6.1/gems/activesupport-5.2.2.1/lib/active_support/execution_wrapper.rb:83:in wrap' | /Users/flatironschool/.rvm/gems/ruby-2.6.1/gems/actioncable-5.2.2.1/lib/action_cable/engine.rb:68:in block (3 级) in '

【问题讨论】:

    标签: javascript ruby-on-rails reactjs websocket actioncable


    【解决方案1】:

    我从学校的 TCF 获得了帮助。

    在我的消息频道中,我将其更改为:

      def subscribed
        @game = Game.find(params[:id][:game_id])
        stream_for @game
      end
    

    所以,stream_for 而不是 stream_from。

    另外,我还改用了 npm 包 react-actioncable-provider。

    我的客户端 javascript 在 React 中,看起来像这样:

    import { ActionCable } from 'react-actioncable-provider';
    import React, { Component, Fragment } from 'react';
    import { CABLE, AUTH_HEADERS } from '../constants';
    import { connect } from 'react-redux';
    import Message from '../components/Message';
    
    class Cable extends Component {
    
      render () {
        console.log("Cable.js")
        return (
          <Fragment>
            <ActionCable
              key={this.props.game_id}
              channel={{ channel: "MessagesChannel", game_id: this.props.game_id }}
              onReceived={(data) => console.log("handleReceived: ", data)}
            />
        </Fragment>
        )
      }
    }
    
    const mapStateToProps = state => {
      return { state }
    }
    
    const mapDispatchToProps = dispatch => {
      return {
        getMessages: data => dispatch({ type: "LOAD_MSGS", payload: data })
      }
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(Cable);
    

    我现在能够接收来自 ActionCable 的响应。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-23
      相关资源
      最近更新 更多