是否可以将 React Native 与 socket.io 结合起来
Is it possible to combine React Native with socket.io
我正在使用 Phonegap + React.js 和 Socket.io 开发一个应用程序。然而,随后 React-Native 发布了,原生的感觉非常棒。
我尝试让 socket.io-client 与 React Native 一起工作,但不幸的是没有太大的成功。我做了一些研究,我得到了与本期中描述的完全相同的错误:https://github.com/facebook/react-native/issues/375
问题上的评论说尝试使用 fetch API 来获取 JS 模块,但我认为我这样做是错误的:
var socketScript;
fetch('https://cdn.socket.io/socket.io-1.2.0.js')
.then(function(response) {
socketScript = response._bodyText;
}).done(function() {
var socket = socketScript.io();
});
这个 returns 一个 undefined 不是函数。
有没有办法让 socket.io-client 与 React Native 一起工作?还是我看错了?也许还有其他更适合的解决方案?
编辑 2016 年 2 月:React Native 现在支持 Web 套接字,因此其中一些建议无效。
恐怕您误解了 Github 问题。其中,aackerman 说:
For this specific case you'll likely want to use the fetch API which
is provided by the environment.
他没有说你应该使用fetchAPI来抓取远程JS模块。他的建议是使用 fetch API 代替内置的 Node.JS 请求模块,后者在 React Native 中不可用。
让我们看看你的代码:
socketScript = response._bodyText;
var socket = socketScript.io();
想一想 - socketScript
不是 JavaScript 对象,它是一个字符串 - 那么你如何调用它的 io
方法?
你真正需要做的是在使用它之前解析 _bodyText
(在浏览器中你可以使用 eval
),但是你仍然会遇到 React Native 的问题有一个用于 XHR 和 fetch API 的 polyfill,它还没有一个用于 WebSocket API。除非我弄错了,这意味着你被卡住了。
我建议打开一个 Github 问题来请求 WebSocket API polyfill 并询问社区的想法。有人可能有解决方法。
缺少 WebSocket API 的 polyfill,您可以创建一个使用网络套接字的本机模块,并使用 eventDispatcher
将事件发送到 Javascript。
在 Javascript 端,您可以使用 DeviceEventEmitter.addListener
订阅这些事件。
有关使用本机模块的详细信息,请参阅 react-native doc on the topic
对于那些像我一样在寻找如何将 socket.io 与 React Native 集成的问题上跌跌撞撞的人。
由于 React Native 支持 websockets 的时间很短,您现在可以使用 Socket.io 非常轻松地设置 web sockets。您所要做的就是以下
- npm 安装socket.io-客户端
- 首先导入 react-native
- 分配
window.navigator.userAgent = 'react-native';
- 导入套接字.io-client/socket.io
- 在你的构造函数中赋值
this.socket = io('localhost:3001', {jsonp: false});
所以在 npm 安装 socket.io-client:
之后它应该看起来像这样
import React from 'react-native';
// ... [other imports]
import './UserAgent';
import io from 'socket.io-client/socket.io';
export default class App extends Component {
constructor(props) {
super(props);
this.socket = io('localhost:3001', {jsonp: false});
}
// now you can use sockets with this.socket.io(...)
// or any other functionality within socket.io!
...
}
然后在 'UserAgent.js':
window.navigator.userAgent = 'react-native';
注意:因为 ES6 模块导入被提升,我们不能在与 react-native 和 socket.io 导入相同的文件中进行 userAgent 分配,因此是单独的模块。
编辑:
上述解决方案应该可行,但在这种情况下它不会尝试创建单独的 socketConfig.js 文件。在那里导入任何需要的东西,包括 const io = require('socket.io-client/socket.io');
并且在需要 socket.io-client 之前有 window.navigator.userAgent = 'react-native';
。然后你可以在那里连接你的套接字并将所有听众放在一个地方。然后可以将动作或函数导入到配置文件中,并在侦听器接收到数据时执行。
现在,如果您想在您的 RN 应用程序中使用 socket.io,您必须使用此代码:
if (!window.location) {
// App is running in simulator
window.navigator.userAgent = 'ReactNative';
}
// This must be below your `window.navigator` hack above
const io = require('socket.io-client/socket.io');
const socket = io('http://chat.feathersjs.com', {
transports: ['websocket'] // you need to explicitly tell it to use websockets
});
socket.on('connect', () => {
console.log('connected!');
});
非常感谢Eric Kryski。
终于找到了。
客户
import { io } from "socket.io-client/build/index"
io("ws://<LOCAL HOME NETWORK IP>:<PORT ON SERVER>")
服务器
import express from "express"
import http from "http"
import * as SocketIO from "socket.io"
const app = express()
const server = new http.Server(app)
const io = new SocketIO.Server(server)
const port = 8000
io.on("connection", socket => {
console.log("CONNECTIONS")
}
import { io } from 'socket.io-client'
const socket = io(`${SOCKET_URL}:${SOCKET_PORT}`)
重要! SOCKET_URL
应该是您的本地 IP 地址,而不是 localhost
或 127.0.0.1
。
检查您的本地 IP:
Mac / Linux: 运行 ifconfig
在终端
Windows: 运行 ipconfig --all
在 shell
应该是这样的:const socket = io('http://10.0.1.6:3000', {transports: ['websocket']})
可能是这将通过错误
import io from "socket.io-client/socket.io"
然后在下面添加一行....
import io from "socket.io-client/dist/socket.io";
然后在 componenDidMount 或 useEffect 函数中添加 line.Never 在 class 组件的构造函数下使用它。
var socket = io("https://localhost.com:3000", { jsonp: false });
// client-side
socket.on("chat_message", (msg) => {
console.log(msg);
});
尽管您可以使用 socket.io-client
库,但社区抱怨大多数版本存在兼容性问题(我确实遇到过一些)。它有效,但现在我不敢升级 lib,因为我需要验证下一个版本与我的服务器版本和 react-native 版本的兼容性!
好像很多人都怀念react's own implementation of Websockets!我真的建议您使用它而不是 socket.io-client
。用法很相似:
var ws = new WebSocket('ws://host.com/path');
ws.onopen = () => { // connection opened ws.send('something'); // send a message};
ws.onmessage = (e) => { // a message was received console.log(e.data);};
ws.onerror = (e) => { // an error occurred console.log(e.message);};
ws.onclose = (e) => { // connection closed console.log(e.code, e.reason);};
2022 年答案
在 2022 年,您可以轻松地使用最新版本的套接字。io-client 和 React Native。
npm install socket.io-client
import io from 'socket.io-client';
目前还没有一个很好的基于 hook 的 socketIO 库,我已经能够使用 RN,但是根据您的需要推出您自己的自定义 hook 非常简单。浏览器
function useWebsocket(url) {
const [connected, setConnected] = useState(false);
const [socket, setSocket] = useState(null);
useEffect(()=>{
const newSocket = io(url);
newSocket.on('connect', ()=>setConnected(true));
newSocket.on('disconnect', ()=>setConnected(false));
setSocket(newSocket);
}, [])
return {
connected,
socket,
}
}
像这样的东西可以让你开始。这将为调用挂钩的每个组件打开一个套接字,如果您只需要一个组件和一个连接,它可以很好地工作。跨组件共享连接有点麻烦,但还不错。
connected
状态对于让您的用户了解连接状态和类似内容非常有用。
但是,是的,关键是您可以安装它并在您的组件中使用它。不要在你的功能组件中使用它
我正在使用 Phonegap + React.js 和 Socket.io 开发一个应用程序。然而,随后 React-Native 发布了,原生的感觉非常棒。
我尝试让 socket.io-client 与 React Native 一起工作,但不幸的是没有太大的成功。我做了一些研究,我得到了与本期中描述的完全相同的错误:https://github.com/facebook/react-native/issues/375
问题上的评论说尝试使用 fetch API 来获取 JS 模块,但我认为我这样做是错误的:
var socketScript;
fetch('https://cdn.socket.io/socket.io-1.2.0.js')
.then(function(response) {
socketScript = response._bodyText;
}).done(function() {
var socket = socketScript.io();
});
这个 returns 一个 undefined 不是函数。
有没有办法让 socket.io-client 与 React Native 一起工作?还是我看错了?也许还有其他更适合的解决方案?
编辑 2016 年 2 月:React Native 现在支持 Web 套接字,因此其中一些建议无效。
恐怕您误解了 Github 问题。其中,aackerman 说:
For this specific case you'll likely want to use the fetch API which is provided by the environment.
他没有说你应该使用fetchAPI来抓取远程JS模块。他的建议是使用 fetch API 代替内置的 Node.JS 请求模块,后者在 React Native 中不可用。
让我们看看你的代码:
socketScript = response._bodyText;
var socket = socketScript.io();
想一想 - socketScript
不是 JavaScript 对象,它是一个字符串 - 那么你如何调用它的 io
方法?
你真正需要做的是在使用它之前解析 _bodyText
(在浏览器中你可以使用 eval
),但是你仍然会遇到 React Native 的问题有一个用于 XHR 和 fetch API 的 polyfill,它还没有一个用于 WebSocket API。除非我弄错了,这意味着你被卡住了。
我建议打开一个 Github 问题来请求 WebSocket API polyfill 并询问社区的想法。有人可能有解决方法。
缺少 WebSocket API 的 polyfill,您可以创建一个使用网络套接字的本机模块,并使用 eventDispatcher
将事件发送到 Javascript。
在 Javascript 端,您可以使用 DeviceEventEmitter.addListener
订阅这些事件。
有关使用本机模块的详细信息,请参阅 react-native doc on the topic
对于那些像我一样在寻找如何将 socket.io 与 React Native 集成的问题上跌跌撞撞的人。
由于 React Native 支持 websockets 的时间很短,您现在可以使用 Socket.io 非常轻松地设置 web sockets。您所要做的就是以下
- npm 安装socket.io-客户端
- 首先导入 react-native
- 分配
window.navigator.userAgent = 'react-native';
- 导入套接字.io-client/socket.io
- 在你的构造函数中赋值
this.socket = io('localhost:3001', {jsonp: false});
所以在 npm 安装 socket.io-client:
之后它应该看起来像这样import React from 'react-native';
// ... [other imports]
import './UserAgent';
import io from 'socket.io-client/socket.io';
export default class App extends Component {
constructor(props) {
super(props);
this.socket = io('localhost:3001', {jsonp: false});
}
// now you can use sockets with this.socket.io(...)
// or any other functionality within socket.io!
...
}
然后在 'UserAgent.js':
window.navigator.userAgent = 'react-native';
注意:因为 ES6 模块导入被提升,我们不能在与 react-native 和 socket.io 导入相同的文件中进行 userAgent 分配,因此是单独的模块。
编辑:
上述解决方案应该可行,但在这种情况下它不会尝试创建单独的 socketConfig.js 文件。在那里导入任何需要的东西,包括 const io = require('socket.io-client/socket.io');
并且在需要 socket.io-client 之前有 window.navigator.userAgent = 'react-native';
。然后你可以在那里连接你的套接字并将所有听众放在一个地方。然后可以将动作或函数导入到配置文件中,并在侦听器接收到数据时执行。
现在,如果您想在您的 RN 应用程序中使用 socket.io,您必须使用此代码:
if (!window.location) {
// App is running in simulator
window.navigator.userAgent = 'ReactNative';
}
// This must be below your `window.navigator` hack above
const io = require('socket.io-client/socket.io');
const socket = io('http://chat.feathersjs.com', {
transports: ['websocket'] // you need to explicitly tell it to use websockets
});
socket.on('connect', () => {
console.log('connected!');
});
非常感谢Eric Kryski。
终于找到了。
客户
import { io } from "socket.io-client/build/index"
io("ws://<LOCAL HOME NETWORK IP>:<PORT ON SERVER>")
服务器
import express from "express"
import http from "http"
import * as SocketIO from "socket.io"
const app = express()
const server = new http.Server(app)
const io = new SocketIO.Server(server)
const port = 8000
io.on("connection", socket => {
console.log("CONNECTIONS")
}
import { io } from 'socket.io-client'
const socket = io(`${SOCKET_URL}:${SOCKET_PORT}`)
重要! SOCKET_URL
应该是您的本地 IP 地址,而不是 localhost
或 127.0.0.1
。
检查您的本地 IP:
Mac / Linux: 运行 ifconfig
在终端
Windows: 运行 ipconfig --all
在 shell
应该是这样的:const socket = io('http://10.0.1.6:3000', {transports: ['websocket']})
可能是这将通过错误
import io from "socket.io-client/socket.io"
然后在下面添加一行....
import io from "socket.io-client/dist/socket.io";
然后在 componenDidMount 或 useEffect 函数中添加 line.Never 在 class 组件的构造函数下使用它。
var socket = io("https://localhost.com:3000", { jsonp: false });
// client-side
socket.on("chat_message", (msg) => {
console.log(msg);
});
尽管您可以使用 socket.io-client
库,但社区抱怨大多数版本存在兼容性问题(我确实遇到过一些)。它有效,但现在我不敢升级 lib,因为我需要验证下一个版本与我的服务器版本和 react-native 版本的兼容性!
好像很多人都怀念react's own implementation of Websockets!我真的建议您使用它而不是 socket.io-client
。用法很相似:
var ws = new WebSocket('ws://host.com/path');
ws.onopen = () => { // connection opened ws.send('something'); // send a message};
ws.onmessage = (e) => { // a message was received console.log(e.data);};
ws.onerror = (e) => { // an error occurred console.log(e.message);};
ws.onclose = (e) => { // connection closed console.log(e.code, e.reason);};
2022 年答案
在 2022 年,您可以轻松地使用最新版本的套接字。io-client 和 React Native。
npm install socket.io-client
import io from 'socket.io-client';
目前还没有一个很好的基于 hook 的 socketIO 库,我已经能够使用 RN,但是根据您的需要推出您自己的自定义 hook 非常简单。浏览器
function useWebsocket(url) {
const [connected, setConnected] = useState(false);
const [socket, setSocket] = useState(null);
useEffect(()=>{
const newSocket = io(url);
newSocket.on('connect', ()=>setConnected(true));
newSocket.on('disconnect', ()=>setConnected(false));
setSocket(newSocket);
}, [])
return {
connected,
socket,
}
}
像这样的东西可以让你开始。这将为调用挂钩的每个组件打开一个套接字,如果您只需要一个组件和一个连接,它可以很好地工作。跨组件共享连接有点麻烦,但还不错。
connected
状态对于让您的用户了解连接状态和类似内容非常有用。
但是,是的,关键是您可以安装它并在您的组件中使用它。不要在你的功能组件中使用它