首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React钩子和ActionCable

React钩子和ActionCable
EN

Stack Overflow用户
提问于 2019-08-09 22:47:25
回答 3查看 1.3K关注 0票数 1

我尝试使用React new Hooks和ActionCable,但仍然存在一个问题,即在尝试发送状态时无法在Rails中获取正确的数据。

我尝试在做完setState()后立即使用send()方法并发送更新后的数据,但由于某些原因,在Rails部分接收的数据是旧的。例如,如果我将" example“输入到输入,我会在Rails端看到"{" data "=>"Exampl"}。我认为数据更新状态的时间比我的请求更新的时间晚。如果我从e.target.value中取值,则一切正常。

因此,我尝试使用新的useEffect()钩子并在那里发送数据。但我只在渲染页面时获得数据。之后,我什么也得不到,有时还会得到错误RuntimeError - Unable to find subscription with an identifier。看起来effect hook发送数据太早了还是怎么的。

我对Hooks和WebSockets还很陌生。很乐意在这里得到任何帮助。我可以共享Rails代码,但只有一个接收器,没有其他东西。

第一个示例:

代码语言:javascript
复制
import React, { useState, useEffect } from "react"
import ActionCable from 'actioncable'

function Component(props) {
const [data, setData] = useState("");

const cable = ActionCable.createConsumer('ws://localhost:3000/cable');
const sub = cable.subscriptions.create('DataChannel');

const handleChange = (e) => {
 setData(e.target.value)
 sub.send({ data });
}

return (
  <input value={data} onChange={handleChange}/>
 )
}

尝试useEffect并将send()移动到那里:

代码语言:javascript
复制
  useEffect(() => {
    sub.send({ data });
  }, [data]);

我很想找到一种正确使用React和ActionCable的方法。如果可能的话,使用钩子。

EN

回答 3

Stack Overflow用户

发布于 2020-09-21 03:22:58

我正在尝试一种类似于奥列格的方法,但我无法在action cable中创建订阅回调( setChannel )。我不得不在回调函数外部但在useEffect钩子内执行setChannel。下面是对我有效的解决方案。

  1. 在index.js中创建消费者,并通过上下文将消费者提供给应用。

代码语言:javascript
复制
index.js

import React, { createContext } from 'react'
import actionCable from 'actioncable'
... omitted other imports

const CableApp = {}
CableApp.cable = actionCable.createConsumer('ws://localhost:3000/cable')
export const ActionCableContext = createContext()

ReactDOM.render(
  <Router>
    ... omitted other providers

    <ActionCableContext.Provider value={CableApp.cable}>
        <App />
    </ActionCableContext.Provider>

  </Router>,
  document.getElementById('root')
)

  1. 使用子组件中的电缆上下文并在useEffect挂钩中创建订阅;在清理

中取消订阅

代码语言:javascript
复制
import React, { useState, useEffect, useContext } from 'react'
import { useParams } from 'react-router-dom'

... omitted code

const [channel, setChannel] = useState(null)
const { id } = useParams()

const cable = useContext(ActionCableContext)
useEffect(() => {
  const channel = cable.subscriptions.create(
    {
      channel: 'MessagesChannel',
      id: id,
    },
    {
      received: (data) => {
        receiveMessage(data)
      },
    }
  )

  setChannel(channel)

  return () => {
    channel.unsubscribe()
  }
}, [id])

const sendMessage = (content) => {
  channel.send(content)
}
票数 2
EN

Stack Overflow用户

发布于 2020-04-27 20:23:25

您可以将电缆注册到根组件,如下所示:

代码语言:javascript
复制
import actionCable from 'actioncable';

(function() {
  window.CableApp || (window.CableApp = {});
  CableApp.cable = actionCable.createConsumer('ws://localhost:3000/cable')
}).call(this);`

因此它将作为全局变量可用;

然后在您想要创建通道和发送数据的任何组件中:

代码语言:javascript
复制
const [channel, setChannel] = useState(null);
          useEffect(() => {
         CableApp.cable.subscriptions.create(
          {
            channel: 'YourChannelName',
          },
          {
            initialized() {
              setChannel(this)
            },
          },
        );
      }, []);

return <button onClick={() => channel.send(some_data)} >Send counter</button>
票数 0
EN

Stack Overflow用户

发布于 2021-03-18 00:51:11

你的问题在这里:

代码语言:javascript
复制
const handleChange = (e) => {
 setData(e.target.value)
 sub.send({ data });
}

setData与setState的相似之处在于,只有在渲染之后,即函数退出之后,才会更新状态。您发送的是当前数据,而不是新数据。试试这个:

代码语言:javascript
复制
const handleChange = (e) => {
 const newData = e.target.value;
 setData(newData)
 sub.send({ data: newData });
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57432487

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档