Javascript作用域和函数
我知道函数在Javascript中是如何闭包的,以及它们如何访问父作用域中声明的变量。在这里,我在一个功能组件中定义了一个名为socket的变量Javascript作用域和函数,javascript,reactjs,socket.io,use-effect,Javascript,Reactjs,Socket.io,Use Effect,我知道函数在Javascript中是如何闭包的,以及它们如何访问父作用域中声明的变量。在这里,我在一个功能组件中定义了一个名为socket的变量 function someName() { const ENDPOINT = "localhost:5000"; let socket useEffect(() => { socket = io(ENDPOINT) // and some code }, [])
function someName() {
const ENDPOINT = "localhost:5000";
let socket
useEffect(() => {
socket = io(ENDPOINT)
// and some code
}, [])
const handleClick = () => {
socket.emit('someEvent', someMessage) // error: cannot read property emit of undefined
}
}
return (
<input />
<button onClick={handleClick}
)
函数someName(){
const ENDPOINT=“localhost:5000”;
插座
useffect(()=>{
套接字=io(端点)
//还有一些代码
}, [])
常量handleClick=()=>{
emit('someEvent',someMessage)//错误:无法读取未定义的属性emit
}
}
返回(
useffect
每次依赖项更改时都会运行。在您的情况下,依赖项是[]
,这意味着它永远不会更改,这意味着useffect永远不会运行多次
因此,每次组件重新渲染时,都会创建一个新的socket
变量,因为useffect
不会再次运行,所以该变量保持未定义
您需要做的是确保在每次重新渲染时返回相同的socket
。最简单和推荐的方法是使用useRef
钩子确保在每次重新渲染时返回相同的值引用
您的代码应该如下所示:
import React, { useEffect, useRef } from 'react';
import io from 'something';
function someName() {
const ENDPOINT = "localhost:5000";
const socket = useRef(null);
useEffect(() => {
socket.current = io(ENDPOINT);
// and some code
}, [])
const handleClick = () => {
socket.current.emit('someEvent', someMessage);
};
return (
<>
<input />
<button onClick={handleClick}
</>
);
}
import React,{useffect,useRef}来自“React”;
从“某物”导入io;
函数someName(){
const ENDPOINT=“localhost:5000”;
const socket=useRef(null);
useffect(()=>{
socket.current=io(端点);
//还有一些代码
}, [])
常量handleClick=()=>{
socket.current.emit('someEvent',someMessage);
};
返回(
useffect
每次依赖项更改时都会运行。在您的情况下,依赖项是[]
,这意味着它永远不会更改,这意味着useffect永远不会运行多次
因此,每次组件重新渲染时,都会创建一个新的socket
变量,因为useffect
不会再次运行,所以该变量保持未定义
您需要做的是确保在每次重新渲染时返回相同的socket
。最简单和推荐的方法是使用useRef
钩子确保在每次重新渲染时返回相同的值引用
您的代码应该如下所示:
import React, { useEffect, useRef } from 'react';
import io from 'something';
function someName() {
const ENDPOINT = "localhost:5000";
const socket = useRef(null);
useEffect(() => {
socket.current = io(ENDPOINT);
// and some code
}, [])
const handleClick = () => {
socket.current.emit('someEvent', someMessage);
};
return (
<>
<input />
<button onClick={handleClick}
</>
);
}
import React,{useffect,useRef}来自“React”;
从“某物”导入io;
函数someName(){
const ENDPOINT=“localhost:5000”;
const socket=useRef(null);
useffect(()=>{
socket.current=io(端点);
//还有一些代码
}, [])
常量handleClick=()=>{
socket.current.emit('someEvent',someMessage);
};
返回(
这里的问题是,在下一次渲染时(在装载回调之后),socket
值被重新定义,其值是未定义的
可能的解决方案如下:
import React, { useEffect } from "react";
import io from "socket.io";
const ENDPOINT = "...";
let socket = io(ENDPOINT);
function Component() {
const handleClick = () => {
socket.emit("someEvent", "some message");
};
return (
<>
<input />
<button onClick={handleClick} />
</>
);
}
import React,{useffect}来自“React”;
从“socket.io”导入io;
const ENDPOINT=“…”;
让套接字=io(端点);
函数组件(){
常量handleClick=()=>{
发出(“someEvent”、“somemessage”);
};
返回(
);
}
请注意,socket.io
应该有一个实例(全局变量/singleton),这样的实例应该在其他文件中公开(导出它),然后每个组件都应该通过修改实例来独立使用它。这里的问题是在下一次渲染时(在装载回调之后),套接字
值被重新定义,其值为未定义
可能的解决方案如下:
import React, { useEffect } from "react";
import io from "socket.io";
const ENDPOINT = "...";
let socket = io(ENDPOINT);
function Component() {
const handleClick = () => {
socket.emit("someEvent", "some message");
};
return (
<>
<input />
<button onClick={handleClick} />
</>
);
}
import React,{useffect}来自“React”;
从“socket.io”导入io;
const ENDPOINT=“…”;
让套接字=io(端点);
函数组件(){
常量handleClick=()=>{
发出(“someEvent”、“somemessage”);
};
返回(
);
}
请注意,socket.io
应该有一个实例(全局变量/singleton),这样的实例应该在其他文件中公开(导出它),然后每个组件都应该通过修改实例来独立使用它。我不认为问题出在使用useEeffect
上。您确定使用的是io(端点)吗
正确吗?您可以看一看。@nibble不幸的是,它是错误的。套接字将在此处未定义。您需要使用一个ref来存储您的套接字id。io
返回什么?@Yousaf它是socket.io,如他的标记中所述。我认为问题不在于您使用的useEeffect
是否确实使用了de>io(端点)
正确吗?您可以看一看。@nibble不幸的是,它是错误的。套接字将在此处未定义。您需要使用一个ref来存储您的套接字id。io
返回什么?@Yousaf如果它是socket.io,如他的标记中所述。单击按钮时,socket.current
beundefined
。@evolutionxbox是的,当然,但这种情况不会发生在真正使用应用程序的人身上,因为useffect
将在页面呈现后立即运行。套接字可能会失败?不确定为什么会被否决,如果这是正确的位置,套接字初始化不是OP所要求的。@evolutionxbox我应该看护吗OP解决了所有这些问题?可能是socket。当点击按钮时,当前的可能是未定义的
。@evolutionxbox肯定是的,但这种情况不会发生在真正使用应用程序的人身上,因为useffect
会在页面呈现后立即运行。socket可能会失败?不确定是什么y这是被否决的,如果这是正确的位置,socket init不是OP所要求的。@evolutionxbox我应该通过所有这些问题来照顾OP吗?为什么在组件外部定义变量会有帮助?如果在上呈现多个组件
s会发生什么