我有一个状态变量,正在通过Websocket更新。在记录变量以检查其状态时,它已经正确更新,但是当我在要使用的函数中引用它时,它是未定义的。我是React和State的新手,不确定自己在做什么错。
在我使用${contactCalling}
的两行中,它都显示为未定义。
任何帮助,不胜感激!
import React from 'react';
import { useState, useEffect } from 'react';
import './App.css';
import socketIOClient from "socket.io-client";
import CallPane from './CallPane'
import '@opentok/client';
import {
SERVER_BASE_URL,
} from './config';
const BASEURL = 'http://localhost:4001'
const socket = socketIOClient(BASEURL);
function App() {
const [callFlag, setCallFlag] = useState(Boolean)
const [apiData, setApiData] = useState([])
const [contactCalling, setContactCalling] = useState('')
console.log(contactCalling)
socket.on("outgoing data", data => {
console.log(data);
setContactCalling(data.caller)
alert(`${contactCalling} is calling you`)
console.log('Call answered')
setCallFlag(true);
});
useEffect ((contactCalling) => {
fetch(SERVER_BASE_URL + `/room/${contactCalling}`)
.then(data => data.json())
.then(data => setApiData(data))
.catch((err) => {
console.error('Failed to get session credentials', err);
alert('Failed to get opentok sessionId and token. Make sure you have updated the config.js file.');
});
},[])
if (callFlag) {
return (
<div className="CallPane">
<CallPane credentials={apiData}/>
</div>
);
} else {
return (
<div className="CallPane">
</div>
);
}
}
export default App;
答案 0 :(得分:0)
我建议从一个基于类的组件开始,而不是从一个功能性的组件开始
创建一个内部带有状态对象的构造函数
并使用componentDidMount
生命周期从套接字获取数据,并在组件正确安装后使用setState
函数将其保存到状态
componentDidMount
生命周期将重新渲染DOM,因此它看起来像是初始渲染。如果获取速度很慢,您会暂时看到它空白,然后将其呈现为所需的状态(它将呈现两次:一次是在获取数据之前,一次是在获取数据完成之后,因此请记住这一点可以在https://reactjs.org/docs/state-and-lifecycle.html处找到有关生命周期的更多信息
您可以使用Redux从Websocket进行提取并将其保存到Redux存储,然后使用它来更新您的组件
希望我的回答有所帮助
答案 1 :(得分:0)
对于您的第一个setContactCalling调用,setContactCalling是一个异步函数。在那样的情况下立即调用它并不能保证值已更改(事实上,它很可能尚未更改)。但是,一旦状态改变,您就可以依靠react再次渲染组件。不用发出警报,只需使用组件中的值即可。也许可以使用模态代替。
对于useEffect内的第二次调用,您尝试将contactCalling传递给该函数...但是该值未定义,因为useEffect不会将任何值传递给该函数。因此它将注销为undefined。值contactCalling将通过useEffect回调之外的setContactCalling设置。与其像您那样传递它,不如将其添加到值数组中以供useEffect观看,就像这样:
useEffect (() => {
fetch(SERVER_BASE_URL + `/room/${contactCalling}`)
.then(data => data.json())
.then(data => setApiData(data))
.catch((err) => {
console.error('Failed to get session credentials', err);
alert('Failed to get opentok sessionId and token. Make sure you have updated the config.js file.');
});
},[contactCalling])