我正在使用 Websockets,但无法弄清楚如何实际显示数据。我是 JS 和 React 的新手,不习惯新的做事方式,特别是因为它在不断变化。
我在 React 中使用 Next.js。这是我运行服务器端的 _app.js
文件。
当我在 onmessage
内使用 setMessages(result) 时,我没有收到任何错误。但我在尝试使用该状态时确实收到错误消息。
我基本上是在尝试显示来自正在连接和工作的 websocket 的数据。正在返回数据。我只需要以某种方式减缓数据流并将其输入到我的组件中。
getApiAndEmit
运行的唯一时间是连接关闭时,并且数据无法返回。控制台登录 client.onclose
显示在前端,所以我想这可能是我将数据返回给客户端的时间。
我想了解做到这一点的最佳方法。并感谢您的帮助。
_app.js
import React, { useEffect, useState } from 'react';
const cors = require('cors');
import '../styles/_variables.scss'
import '../styles/_all.scss'
import '../node_modules/react-vis/dist/style.css';
import {w3cwebsocket as W3CWebSocket} from "websocket/lib/websocket"
// App currently does not support Next.js Data Fetching methods like getStaticProps or getServerSideProps.
function MyApp({ Component, pageProps }) {
const [messageText, setMessageText] = useState("");
const [receivedMessages, setMessages] = useState([]);
const messageTextIsEmpty = messageText.trim().length === 0;
const client = new W3CWebSocket('wss://ws-feed.pro.coinbase.com');
const channel = {
"type": "subscribe",
"product_ids": [
"BTC-USD",
"BTC-EUR"
],
"channels": [
"heartbeat",
"level2",
{
"name": "ticker",
"product_ids": [
"BTC-USD"
]
}
]
}
let interval;
const getApiAndEmit = (type,result) => {
//const response = new Date();
// Emitting a new message. Will be consumed by the client
console.log("getApiAndEmit");
console.log(result)
//socket.emit("FromAPI", response);
};
// shows up in front end console.
client.onclose = (socket) => {
console.log("onclose socket cleear interveal");
console.log(socket);
if (interval) {
clearInterval(interval);
}
interval = setInterval(() => getApiAndEmit("onclose","onclose"), 5000);
}
// TODO: flooding, constantly opening?
client.onopen = (socket) => {
console.log("OPEN intetval")
if (interval) {
console.log("OPEN clearInterval")
clearInterval(interval);
}
interval = setInterval(() => getApiAndEmit("OPEN "," OPEN "), 5000);
// clear interval didn't work well here
client.send(JSON.stringify(channel));
};
// runs millions of times
client.onmessage = (message) => {
// filter updates to products, not connections, etc
const result = JSON.parse(message.data)
const type = result.type;
switch(type) {
case 'subscriptions':
break;
case 'ticker':
// runs server side!
//console.log("setting message",result)
if (interval) {
console.log("CLEAR interval")
clearInterval(interval);
} else {
console.log("DO NOT CLEAR interval")
interval = setInterval(() => getApiAndEmit(type,result), 5000);
}
setMessages(result)
// old way
//this.setState({dataFromServer: result})
//const [count, setCount] = useState(0);
break;
default:
// code block
}
/*
response
{
"type": "ticker",
"sequence": 3074716831,
"product_id": "ETH-BTC",
"price": "0.03076",
"open_24h": "0.03111",
"volume_24h": "14209.34102156",
"low_24h": "0.03057",
"high_24h": "0.03143",
"volume_30d": "824694.85566290",
"best_bid": "0.03076",
"best_ask": "0.03077",
"side": "sell",
"time": "2021-03-22T21:34:21.464755Z",
"trade_id": 14723995,
"last_size": "2.19802296"
}
*/
};
return <Component {...pageProps} />
}
export default MyApp
我的组件在尝试访问状态时收到错误消息
import Link from 'next/link'
import useSwr from "swr"
import {useRouter} from "next/router"
import React, { useState, useEffect } from 'react';
const SimpleTicker = (props) => {
/*
function dispatchAction(fiber, queue, action) {
{
if (typeof arguments[3] === 'function') {
error("State updates from the useState()
and useReducer() Hooks don't support the " + 'second callback argument.
To execute a side effect after ' + 'rendering, declare it in the component body with useEffect().');
}
*/
//const [messageText, setMessageText] = useState("");
//const [receivedMessages, setMessages] = useState([]);
return (
<div className={`ticker ticker-${props.crypto}`}>
<div>${props.crypto}</div>
{/*<span>{data.ticker.price}</span>*/}
</div>
);
};
export default SimpleTicker;