Javascript React组件在重新渲染时创建状态的新实例,即使状态未更改
我将Javascript React组件在重新渲染时创建状态的新实例,即使状态未更改,javascript,reactjs,websocket,socket.io,Javascript,Reactjs,Websocket,Socket.io,我将Socket.IO与React.js一起使用,我希望websocket仅在呈现特定组件时启动,因此我将websocket用作该组件的状态,如下所示: const Comp = () => { const {current: instance} = useRef({}); const ws = instance.ws = instance.ws || socketIO(); // ... the rest of the component ... }; const Comp
Socket.IO
与React.js
一起使用,我希望websocket仅在呈现特定组件时启动,因此我将websocket用作该组件的状态,如下所示:
const Comp = () => {
const {current: instance} = useRef({});
const ws = instance.ws = instance.ws || socketIO();
// ... the rest of the component ...
};
const Comp=()=>{
const[ws]=useState(socketIO());
//…组件的其余部分。。。
};
但是当
Comp
重新呈现时,它会创建新的websocket连接,即使我没有对连接进行任何更改。过了一段时间,我得到了超过10个websocket连接。如何使组件仅保持1个连接?我不希望websocket连接成为全局连接。记住,功能组件只是函数,所有关于函数的常见知识都适用。虽然钩子在幕后发挥了一些看似神奇的作用(这不是真正的神奇,只是它们有我们看不到的上下文信息),但组件函数中的代码按照通常的规则运行。这意味着这个代码
const Comp = () => {
const [ws] = useState(socketIO());
// ... the rest of the component ...
};
将始终调用socketIO
,以便它可以将其返回值传递到useState
要仅计算一次值,当组件第一次创建时,请使用ref()表示非状态实例信息(这类信息将直接存储在类组件实例上),如下所示:
const Comp = () => {
const {current: instance} = useRef({});
const ws = instance.ws = instance.ws || socketIO();
// ... the rest of the component ...
};
{}
仍然在每次调用Comp
时进行计算,但这种开销很小。您从useRef
中得到的是一个对象,该对象具有一个current
属性,该属性引用一个可变对象,该对象在组件的整个生命周期内始终相同。第二行使用该对象的ws
属性,如果它是falsy,则第一次初始化它
此用法在以下文件中列出:
但是,useRef()
不仅适用于ref属性。它可以方便地保留任何可变值,类似于在类中使用实例字段的方式
下面是一个示例,其中有一个替代socketIO
:
const{useRef,useState}=React;
函数socketIO(){
log(“socketIO调用”);
返回{};
}
常数Comp=()=>{
控制台日志(“被调用的组件”);
const{current:instance}=useRef({});
常量ws=instance.ws=instance.ws | | socketIO();
const[counter,setCounter]=useState(0);
返回(
{counter}setCounter(c=>c+1)}/>
);
};
render(,document.getElementById(“根”))代码>
感谢您的详细回答。但是你能在这里给我解释一下链接分配吗:const ws=instance.ws=instance.ws | | socketIO()
?@TríPhan-该表达式的工作原理如下:它计算instance.ws | | socketIO()
,这意味着|
运算符计算左手操作数(instance.ws
),并且如果结果是真的(除null
,未定义的
,0
,NaN
,)
,或false
),它将该值作为其结果。如果左侧运算符的值为falsy(这些值中的任何一个),它将计算右侧(调用socketIO
)并将该结果作为其结果。然后完成第一个赋值(instance.ws=x
,其中x
是第一个表达式的结果)。赋值的结果就是被赋值的值,所以表达式的结果也是x
。然后完成ws=x
部分。因此,第一次创建组件并运行Comp
时,由于instance
将是一个空白对象,instance.ws
将未定义,并且socketIO
将被调用;结果将分配给instance.ws
和ws
。下次调用Comp
时,instance.ws
将已经有一个truthy值,因此不会调用socketIO
,而ws
将获取该值。