在带有 React 的 Rails 中使用 ActionCable
在带有 React 的 Rails 中使用 ActionCable
在 Rails 应用程序中加入实时交互的能力是通过 行动电缆 ,这是几年前在 Rails 5 中引入的。虽然 任何电缆 现在提供了一个更快的替代方案,我决定使用 ActionCable 作为我第一次涉足 WebSockets。
以下是我将 ActionCable 与 react 结合到我的 rails 应用程序中所采取的基本步骤。
安装 npm 包 对于可操作的:
npm i 可操作
取消注释 gemfile 中的 redis gem,然后运行 bundle install
# 使用 Redis 适配器在生产环境中运行 Action Cable 宝石“返回”,“〜> 4.0”
在您的 routes.rb 文件中,挂载 ActionCable:
mount ActionCable.server => '/cable'
接下来,使用 rails g channel 生成一个通道
rails g 频道消息
为了在前端引入 ActionCable,请将 actioncable npm 包导入 index.js 文件:
从“actioncable”导入 actionCable
然后通过声明一个变量将其带入应用程序。
常量 cableApp = {} cableApp.cable = actionCable.createConsumer("ws://localhost:3000/cable")
有几种方法可以通过您的应用程序将其传递,但我采用以下路线,将其作为道具传递(同时还将 App 包装在其他全局变量的上下文中,在这种情况下我没有将其用于 ActionCable):
返回 ( <div> <UserContext.Provider value={value}> <App cableApp={cableApp}/> </UserContext.Provider> </div> )
然后我在 props 中将它传递给一个组件,该组件将在用户导航到聊天室时挂载(在我的应用程序中,我创建了一个名为 Conversation 的模型,因此 /conversations/:id)。在该组件中,将挂载一个子组件,该子组件将作为 websocket 组件服务。这背后的想法是进入对话室会初始化 websocket 连接。
这是 ConvoWebSocket 组件,它正在做几件事:
-
接收道具(其中之一是从 index.js 穿过的电缆对象)
-
挂载时运行 useEffect,并将对话 ID 声明为依赖项。
-
使用 ActionCable 方法为 MessagesChannel 通道和对话 ID 创建使用者。
-
然后利用 ActionCable 中接收到的方法(这是一个重要的步骤,我很快就会回来)将数据发送到我称为 tellMe() 的函数。
从“反应”导入反应,{useEffect} const ConvoWebSocket = (props) => { 使用效果(()=> { const conversationId = window.location.href.match(/\d+$/)[0] props.cableApp.room = props.cableApp.cable.subscriptions.create( { 频道:“消息频道”, 房间:conversationId }, { 收到:(数据)=> { if (parseInt(props.conversationId) === data.message.conversation_id) { props.tellMe(数据) }}, })}, [props.conversationId]) 返回 (
下面是(可能命名不准确)tellMe() 函数是从父级 ConversationRoom 组件向下传递的:
常量告诉我=(数据)=> { setConvoMessages((convoMessages) => [...convoMessages, data.message]) }
该函数接收从received方法传入的数据(前面提到过),然后更新消息的状态变量,然后显示在聊天中。
生成消息通道时,创建的文件之一是 MessagesChannel.rb 文件,您可以在通道文件夹中找到该文件。
在此文件中为您创建了三种默认方法 - 订阅、接收和取消订阅。必须在您的应用程序中调用此接收到的方法才能与通过 WebSocket 连接传递的数据进行交互。
类 MessagesChannel < ApplicationCable::Channel 默认订阅 stop_all_streams @conversation = Conversation.find(params[:room]) stream_for @conversation 结尾 def 收到(数据) 结尾 默认取消订阅 stop_all_streams 结尾 结尾
ActionCable 方法也可以在控制器中调用,这是我在我的应用程序中选择的。我的理由是,当发送一条新消息时,它既需要保存到模型中(提交给数据库),又需要广播到对话中(发送给消费者)
定义创建 @message = current_user.messages.build(message_params) @conversation = Conversation.find(message_params["conversation_id"]) 如果@message.save MessagesChannel.broadcast_to(@conversation, {message: @message.serializable_hash(include: :user) } ) 结尾 结尾
我希望这对其他开始使用 Action Cable 的人有所帮助。我建议检查 动作电缆文档 ,尤其是在底部提供了一些全栈(尽管是导轨)示例的地方。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明