如何在我的 React 应用程序中创建单独的动态 window?
How can I create a separate dynamic window in my React app?
我的 React 应用程序包含视频聊天功能(通过 Twilio)。用户转到仪表板,然后单击按钮开始通话。这会提示 VideoCall
组件被实例化并显示。在实例化时,它连接到后端 Twilio 服务以获取访问令牌,然后连接到 Twilio 以创建调用、设置事件处理程序等。
目前我在仪表板的 div 中显示视频 windows,但我希望它们显示在弹出窗口 window 中。我已经尝试过使用 react-new-window 并且我已经尝试过 React Portals,但是我对我正在做的事情了解不够。
目前我有以下 Dashboard
组件:
function Dashboard(props) {
const { displayInfo} = props
const [ callInitiated, setCallInitiated ] = useState(false)
const initCall = () => {
setCallInitiated(true)
}
return (
<div id="dashboard">
{callInitiated ? <VideoCall displayInfo={displayInfo} /> : null }
<div> ...rest of dashboard, including button which calls 'initCall' on being clicked... </div>
</div>
)
}
export default Dashboard
我的 VideoCall
组件是:
const Video = require('twilio-video');
// Get access token from backend service
async function getAccessToken(identity) {
const url = `${process.env.REACT_APP_TWILIO_TOKEN_SERVICE}?identity=${identity}`;
try {
const response = await axios.get(`${url}`, AXIOS_HEADERS);
return response.data.accessToken;
} catch {
return null;
}
}
// VideoCall component
function VideoCall(props) {
const { displayInfo} = props
// Connect to Twilio server function to get access token
getAccessToken('Tester')
.then((token) => {
Video.connect(token, {
name: 'Test room'
})
.then(room => {
participantConnected(room.localParticipant);
room.participants.forEach(participantConnected);
room.on('participantConnected', participantConnected);
room.on('participantDisconnected', participantDisconnected);
room.once('disconnected', error => room.participants.forEach(participantDisconnected))
})
});
function participantConnected(participant) {
const div = document.createElement('div');
div.id = participant.sid;
participant.on('trackSubscribed', track => trackSubscribed(div, track));
participant.on('trackUnsubscribed', trackUnsubscribed);
participant.tracks.forEach(publication => {
trackSubscribed(div, publication.track);
});
if(participant.identity === 'Tester') {
document.getElementById('myVideoWindow').appendChild(div)
}
}
function participantDisconnected(participant) {
document.getElementById(participant.sid).remove();
}
function trackSubscribed(div, track) {
div.appendChild(track.attach());
}
function trackUnsubscribed(track) {
track.detach().forEach(element => element.remove());
}
return (
<div id="callWrapper" className="callOuterWrapper">
<div className="titleBar">
<h1 className="pageHeader">Calling {displayInfo.receiverName}</h1>
</div>
<div className="videoRoom">
<div id="myVideoWindow" className="callWindow"></div>
<div className="callInfo"> ...this will contain info on call status... </div>
<div id="receiverWindow" className="callWindow"></div>
</div>
</div>
)
}
export default VideoCall
到目前为止,这有效。用户单击该按钮,视频 windows 出现在仪表板的顶部,如预期的那样。
现在我想将 VideoCall
组件拉出到一个单独的 window 中(这样用户在通话时仍然可以看到仪表板。
我尝试了包 react-new-window,它只涉及将 VideoCall
包装在 NewWindow
中。我尝试将其包装在 Dashboard
组件中:
<div id="dashboard">
{callInitiated ? <NewWindow><VideoCall displayInfo={displayInfo} /></NewWindow> : null }
<div> ...rest of dashboard, including button which calls 'initCall' on being clicked... </div>
</div>
当这不起作用时,我尝试在 VideoCall
组件中包装:
<NewWindow>
<div id="callWrapper" className="callOuterWrapper">...</div>
</NewWindow>
在这两种情况下,这显示了新的 window 和空的 callWrapper
div;然而,一旦到达 document.getElementById('myVideoWindow').appendChild(div)
,它就无法找到 div。被引用的 DOM 似乎是仪表板 window 中的那个,而不是新的 windows(另外,任何 console.log
命令都会记录到原始 window,不是新的)。
然后我尝试拆开 NewWindow 代码并创建我自己的定制版本,但我不太了解它是如何工作的,无法让它执行我需要的操作。
那么,有没有办法从其中的组件访问新 window 的 DOM?或者我应该采取不同的方法吗?
此处为 Twilio 开发人员布道师。
直接访问 DOM 使用本机 DOM 方法,如 document.getElementById
,在 React 中有点不受欢迎。 React 本身应该负责在 DOM.
中添加和删除内容
我在 how to build a video chat with React 上写了一篇 post,介绍了如何在不直接访问 DOM 的情况下将参与者添加到页面。
我建议您仔细阅读一下,或许还可以更新您的应用程序,这样您就不必使用 document.getElementById
,然后希望 <NewWindow>
组件能够像宣传的那样工作。
我的 React 应用程序包含视频聊天功能(通过 Twilio)。用户转到仪表板,然后单击按钮开始通话。这会提示 VideoCall
组件被实例化并显示。在实例化时,它连接到后端 Twilio 服务以获取访问令牌,然后连接到 Twilio 以创建调用、设置事件处理程序等。
目前我在仪表板的 div 中显示视频 windows,但我希望它们显示在弹出窗口 window 中。我已经尝试过使用 react-new-window 并且我已经尝试过 React Portals,但是我对我正在做的事情了解不够。
目前我有以下 Dashboard
组件:
function Dashboard(props) {
const { displayInfo} = props
const [ callInitiated, setCallInitiated ] = useState(false)
const initCall = () => {
setCallInitiated(true)
}
return (
<div id="dashboard">
{callInitiated ? <VideoCall displayInfo={displayInfo} /> : null }
<div> ...rest of dashboard, including button which calls 'initCall' on being clicked... </div>
</div>
)
}
export default Dashboard
我的 VideoCall
组件是:
const Video = require('twilio-video');
// Get access token from backend service
async function getAccessToken(identity) {
const url = `${process.env.REACT_APP_TWILIO_TOKEN_SERVICE}?identity=${identity}`;
try {
const response = await axios.get(`${url}`, AXIOS_HEADERS);
return response.data.accessToken;
} catch {
return null;
}
}
// VideoCall component
function VideoCall(props) {
const { displayInfo} = props
// Connect to Twilio server function to get access token
getAccessToken('Tester')
.then((token) => {
Video.connect(token, {
name: 'Test room'
})
.then(room => {
participantConnected(room.localParticipant);
room.participants.forEach(participantConnected);
room.on('participantConnected', participantConnected);
room.on('participantDisconnected', participantDisconnected);
room.once('disconnected', error => room.participants.forEach(participantDisconnected))
})
});
function participantConnected(participant) {
const div = document.createElement('div');
div.id = participant.sid;
participant.on('trackSubscribed', track => trackSubscribed(div, track));
participant.on('trackUnsubscribed', trackUnsubscribed);
participant.tracks.forEach(publication => {
trackSubscribed(div, publication.track);
});
if(participant.identity === 'Tester') {
document.getElementById('myVideoWindow').appendChild(div)
}
}
function participantDisconnected(participant) {
document.getElementById(participant.sid).remove();
}
function trackSubscribed(div, track) {
div.appendChild(track.attach());
}
function trackUnsubscribed(track) {
track.detach().forEach(element => element.remove());
}
return (
<div id="callWrapper" className="callOuterWrapper">
<div className="titleBar">
<h1 className="pageHeader">Calling {displayInfo.receiverName}</h1>
</div>
<div className="videoRoom">
<div id="myVideoWindow" className="callWindow"></div>
<div className="callInfo"> ...this will contain info on call status... </div>
<div id="receiverWindow" className="callWindow"></div>
</div>
</div>
)
}
export default VideoCall
到目前为止,这有效。用户单击该按钮,视频 windows 出现在仪表板的顶部,如预期的那样。
现在我想将 VideoCall
组件拉出到一个单独的 window 中(这样用户在通话时仍然可以看到仪表板。
我尝试了包 react-new-window,它只涉及将 VideoCall
包装在 NewWindow
中。我尝试将其包装在 Dashboard
组件中:
<div id="dashboard">
{callInitiated ? <NewWindow><VideoCall displayInfo={displayInfo} /></NewWindow> : null }
<div> ...rest of dashboard, including button which calls 'initCall' on being clicked... </div>
</div>
当这不起作用时,我尝试在 VideoCall
组件中包装:
<NewWindow>
<div id="callWrapper" className="callOuterWrapper">...</div>
</NewWindow>
在这两种情况下,这显示了新的 window 和空的 callWrapper
div;然而,一旦到达 document.getElementById('myVideoWindow').appendChild(div)
,它就无法找到 div。被引用的 DOM 似乎是仪表板 window 中的那个,而不是新的 windows(另外,任何 console.log
命令都会记录到原始 window,不是新的)。
然后我尝试拆开 NewWindow 代码并创建我自己的定制版本,但我不太了解它是如何工作的,无法让它执行我需要的操作。
那么,有没有办法从其中的组件访问新 window 的 DOM?或者我应该采取不同的方法吗?
此处为 Twilio 开发人员布道师。
直接访问 DOM 使用本机 DOM 方法,如 document.getElementById
,在 React 中有点不受欢迎。 React 本身应该负责在 DOM.
我在 how to build a video chat with React 上写了一篇 post,介绍了如何在不直接访问 DOM 的情况下将参与者添加到页面。
我建议您仔细阅读一下,或许还可以更新您的应用程序,这样您就不必使用 document.getElementById
,然后希望 <NewWindow>
组件能够像宣传的那样工作。