Javascript 如何使用React钩子使React门户工作?
我特别需要在浏览器中收听自定义事件,我有一个按钮可以打开一个弹出窗口。我目前正在使用React门户打开另一个窗口(PopupWindow),但当我在其中使用钩子时,它不起作用——但如果我使用类,它就会起作用。通过工作,我的意思是,当窗口打开时,两个窗口都显示其下方的div,但当事件中的数据刷新时,带有挂钩的窗口会将其删除。要进行测试,请将车窗打开至少5秒钟 我在CodeSandbox中有一个例子,但我也会在这里发布,以防网站关闭或其他情况: 下面的代码不会运行,因为我不知道如何通过react cdn使react钩子工作,但您现在可以使用上面的链接进行测试Javascript 如何使用React钩子使React门户工作?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我特别需要在浏览器中收听自定义事件,我有一个按钮可以打开一个弹出窗口。我目前正在使用React门户打开另一个窗口(PopupWindow),但当我在其中使用钩子时,它不起作用——但如果我使用类,它就会起作用。通过工作,我的意思是,当窗口打开时,两个窗口都显示其下方的div,但当事件中的数据刷新时,带有挂钩的窗口会将其删除。要进行测试,请将车窗打开至少5秒钟 我在CodeSandbox中有一个例子,但我也会在这里发布,以防网站关闭或其他情况: 下面的代码不会运行,因为我不知道如何通过react
const{useState,useffect}=React;
函数getRandom(最小值、最大值){
const first=Math.ceil(最小值)
最后常数=数学楼层(最大值)
返回Math.floor(Math.random()*(last-first+1))+first
}
函数replaceWithRandom(someData){
让newData={}
for(让d输入一些数据){
newData[d]=getRandom(someData[d],someData[d]+500)
}
返回新数据
}
const PopupWindowWithHooks=props=>{
const containerell=document.createElement('div')
让externalWindow=null
使用效果(
() => {
externalWindow=window.open(
'',
'',
`宽度=600,高度=400,左侧=200,顶部=200`
)
externalWindow.document.body.appendChild(containerell)
externalWindow.addEventListener('beforeunload',()=>{
props.closePopupUpfinowWithhooks()
})
console.log('创建的弹出窗口')
返回函数cleanup(){
console.log('已清理的弹出窗口')
externalWindow.close()
externalWindow=null
}
},
//仅当变量更改时才重新呈现此组件
[]
)
返回ReactDOM.createPortal(props.children,containerell)
}
类PopupWindow扩展了React.Component{
containerell=document.createElement('div')
externalWindow=null
componentDidMount(){
this.externalWindow=window.open(
'',
'',
`宽度=600,高度=400,左侧=200,顶部=200`
)
this.externalWindow.document.body.appendChild(this.containerell)
this.externalWindow.addEventListener('beforeunload',()=>{
this.props.closePopupWindow()
})
console.log('创建的弹出窗口')
}
组件将卸载(){
console.log('已清理的弹出窗口')
this.externalWindow.close()
}
render(){
返回ReactDOM.createPortal(
这个,道具,孩子们,
这是集装箱鱼
)
}
}
函数App(){
让数据={
大约600,
其他:200
}
让[dataState,setDataState]=useState(数据)
useffect(()=>{
let interval=setInterval(()=>{
setDataState(replaceWithRandom(dataState))
const event=new CustomEvent('onOverlayDataUpdate'{
详细信息:数据状态
})
文件。dispatchEvent(事件)
}, 5000)
返回函数clear(){
清除间隔(间隔)
}
}, [])
使用效果(
函数getData(){
document.addEventListener('onOverlayDataUpdate',e=>{
setDataState(如详细信息)
})
返回函数cleanup(){
document.removeEventListener(
“onOverlayDataUpdate”,
文件
)
}
},
[数据状态]
)
console.log(数据状态)
//状态处理
const[isPopupWindowOpen,setIsPopupWindowOpen]=useState(false)
常数[
isPopupWindowWithHooksOpen,
设置iPopupWithHooksopen
]=使用状态(false)
常量togglePopupWindow=()=>
setIsPopupWindowOpen(!isPopupWindowOpen)
const togglePopupWithhooks=()=>
setIsPopupWindowWithHooksOpen(!isPopupWindowWithHooksOpen)
const closePopupWindow=()=>setIsPopupWindowOpen(false)
const closePopupWindowWithHooks=()=>
setIsPopupWindowWithHooksOpen(假)
//副作用
useffect(()=>
window.addEventListener('beforeunload',()=>{
closePopupWindow()
closePopupWindowWithHooks()
})
)
返回(
切换窗口
用钩子拨动窗户
{isPopupWindowOpen&&(
这是怎么回事?
我应该一直在这里!
)}
{isPopupWindowWithHooksOpen&&(
这是怎么回事?
我应该一直在这里!
)}
)
}
const rootElement=document.getElementById('root'))
ReactDOM.render(,rootElement)
const[containerell]=useState(document.createElement('div')代码>
编辑
单击事件按钮,首先调用功能组件PopupUpIndowWithHooks的调用,它将按预期工作(在useEffect中创建新的
,将
附加到弹出窗口)
事件刷新,调用功能组件PopupWindowWithHooks的第二次调用,并再次行const containerell=document.createElement('div')
创建新的
。但是(第二个)新的
将永远不会追加到弹出窗口中,因为行externalWindow.document.body.appendChild(containerell)
正在使用,它将只在装载时运行,在卸载时清除(第二个参数是空数组[])
最后返回ReactDOM.createPortal(props.children,containeerre)
使用第二个参数containeerre创建门户-新的未终止
使用Containerere作为有状态值(useState钩子),问题得到解决:
const [containerEl] = useState(document.createElement('div'));
EDIT2
代码沙盒:问题是:在每个渲染上创建一个新的div
,只需在渲染外部创建div
功能和它应该按预期工作
const containerEl = document.createElement('div')
const PopupWindowWithHooks = props => {
let externalWindow = null
... rest of your code ...
const门户=({children})=>{
const[modalContainer]=useState(document.createElement('div');
useffect(()=>{
//在DOM中查找根元素
乐
const App = () => (
<Portal>
<MyModal />
</Portal>
)
import { useLayoutEffect, useRef } from "react";
import { createPortal } from "react-dom";
const useCreatePortalInBody = () => {
const wrapperRef = useRef(null);
if (wrapperRef.current === null && typeof document !== 'undefined') {
const div = document.createElement('div');
div.setAttribute('data-body-portal', '');
wrapperRef.current = div;
}
useLayoutEffect(() => {
const wrapper = wrapperRef.current;
if (!wrapper || typeof document === 'undefined') {
return;
}
document.body.appendChild(wrapper);
return () => {
document.body.removeChild(wrapper);
}
}, [])
return (children => wrapperRef.current && createPortal(children, wrapperRef.current);
}
const Demo = () => {
const createBodyPortal = useCreatePortalInBody();
return createBodyPortal(
<div style={{position: 'fixed', top: 0, left: 0}}>
In body
</div>
);
}
import usePortal from 'react-useportal'
const App = () => {
const { openPortal, closePortal, isOpen, Portal } = usePortal()
return (
<>
<button onClick={openPortal}>
Open Portal
</button>
{isOpen && (
<Portal>
<p>
This is more advanced Portal. It handles its own state.{' '}
<button onClick={closePortal}>Close me!</button>, hit ESC or
click outside of me.
</p>
</Portal>
)}
</>
)
}