我尝试使用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代码,但只有一个接收器,没有其他东西。
第一个示例:
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()移动到那里:
useEffect(() => {
sub.send({ data });
}, [data]);我很想找到一种正确使用React和ActionCable的方法。如果可能的话,使用钩子。
发布于 2020-09-21 03:22:58
我正在尝试一种类似于奥列格的方法,但我无法在action cable中创建订阅回调( setChannel )。我不得不在回调函数外部但在useEffect钩子内执行setChannel。下面是对我有效的解决方案。
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')
)中取消订阅
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)
}发布于 2020-04-27 20:23:25
您可以将电缆注册到根组件,如下所示:
import actionCable from 'actioncable';
(function() {
window.CableApp || (window.CableApp = {});
CableApp.cable = actionCable.createConsumer('ws://localhost:3000/cable')
}).call(this);`因此它将作为全局变量可用;
然后在您想要创建通道和发送数据的任何组件中:
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>发布于 2021-03-18 00:51:11
你的问题在这里:
const handleChange = (e) => {
setData(e.target.value)
sub.send({ data });
}setData与setState的相似之处在于,只有在渲染之后,即函数退出之后,才会更新状态。您发送的是当前数据,而不是新数据。试试这个:
const handleChange = (e) => {
const newData = e.target.value;
setData(newData)
sub.send({ data: newData });
}https://stackoverflow.com/questions/57432487
复制相似问题