我有一个状态变量,我正在通过websocket更新。当记录变量以检查其状态时,它已正确更新,但是当我在函数中引用它以供使用时,它是未定义的。我是 React 和状态的新手,不确定我做错了什么。
在我使用${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;
我建议从基于类的组件而不是功能组件开始
创建一个内部包含状态对象的构造函数
并使用componentDidMount
生命周期从套接字获取数据,并在组件正确挂载后使用setState
函数将其保存到状态
componentDidMount
生命周期将重新渲染 DOM,使其看起来像是初始渲染。如果获取速度很慢,您将看到它暂时空白,然后渲染到您需要的样子(它会渲染两次:一次在获取数据之前,一次在获取数据完成时,所以请记住,您可以在此处找到有关生命周期的更多信息 https://reactjs.org/docs/state-and-lifecycle.html(
从 websocket 进行获取并将其保存到 Redux 存储中,然后使用它更新您的组件
希望我的回答有所帮助
对于您的第一个 setContactCalling 调用,setContactCalling 是一个异步函数。像这样之后立即调用它并不能保证该值已更改(事实上,它很可能尚未更改(。但是,一旦状态发生变化,您可以依靠 react 再次渲染组件。只需使用组件中的值,而不是警报。也许改用模态。
对于 useImpact 内部的第二次调用,您正在尝试将 contactCalling 传递到函数中...但是该值是未定义的,因为 useEffect 不会向其传递任何内容。因此,它将注销为未定义。值 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])