在不重新加载页面的情况下测量组件的宽度
Measure width of component without re-loading the page
我正在使用这个钩子来测量 div 组件 (https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node) 的大小:
function useClientRect() {
const [rect, setRect] = React.useState(null);
const ref = React.useCallback(node => {
if (node !== null) {
setRect(node.getBoundingClientRect());
}
}, []);
return [rect, ref];
}
这是我的组件,经过简化。我将它与 React Map GL 一起使用,因为无法根据 % 设置视口的宽度。我找不到其他方法...getBoundsForPoints 是一个函数,用于获取地图视口的限制,给定坐标数组和以像素为单位的地图宽度。
function Mapas(props){
const [rect,ref] = useClientRect()
useEffect(()=>{
const coordinates = [some coordinates]
let new_viewport
if (rect!==null){ //Here is when sometimes I get rect===null
new_viewport = getBoundsForPoints(coordinates, rect.width)
} else {
new_viewport = getBoundsForPoints(coordinates, 500)
}
setViewport(new_viewport)
},[rect])
return (
<MDBContainer>
<MDBRow>
<MDBCol md='12' xl='8'>
<div ref={ref}> {/*Elemento referenciado */}
<ReactMapGL
{...viewport}
mapboxApiAccessToken='xxx'}
mapStyle='xxx'
onViewportChange={nextViewport => setViewport({...nextViewport})}
>
</ReactMapGL>
</div>
</MDBCol>
<MDBCol xl='4' md='12'>
Other stuff
</MDBCol>
</MDBRow>
</MDBContainer>
)
}
export default Mapas
页面加载后工作正常;然而,当我从其他组件到达页面时,没有重新渲染,rect 为空。我怎样才能避免这种情况,谢谢!
import ResizeObserver from 'resize-observer-polyfill';
const measureSize = el => {
return {
height: el && el.current && Math.round(el.current.getBoundingClientRect().height),
width: el && el.current && Math.round(el.current.getBoundingClientRect().width),
};
};
const [size, setSize] = useState(measureSize(ref));
useEffect(() => {
setSize(measureSize(ref));
const observer = new ResizeObserver(() => {
window.requestAnimationFrame(() => {
setSize(measureSize(ref));
});
});
observer.observe(ref.current);
return () => {
observer.disconnect();
};
}, [ref]);
我使用 polyfill resize-observer-polyfill
以获得更强大的解决方案
我终于不得不使用钩子 useLayoutEffect,而不是 useEffect。钩子 (https://es.reactjs.org/docs/hooks-reference.html#uselayouteffect) 与 useEffect 类似,但在构建所有组件后是 运行,因此引用现在已正确定义并且可以测量组件的尺寸。
最终的简化代码如下:
function useClientRect() {
const [rect, setRect] = React.useState(null);
const ref = React.useCallback(node => {
console.log('Node')
console.log(node)
if (node !== null) {
setRect(node.getBoundingClientRect());
}
}, []);
return [rect, ref];
}
function Mapas(props){
const [rect,ref] = useClientRect()
useLayoutEffect(()=>{
const coordinates = [some coordinates]
let new_viewport
if (rect!==null){ //Here is when sometimes I get rect===null
new_viewport = getBoundsForPoints(coordinates, rect.width)
} else {
new_viewport = getBoundsForPoints(coordinates, 500)
}
setViewport(new_viewport)
},[rect])
return (
<MDBContainer>
<MDBRow>
<MDBCol md='12' xl='8'>
<div ref={ref}> {/*Elemento referenciado */}
<ReactMapGL
{...viewport}
mapboxApiAccessToken='xxx'}
mapStyle='xxx'
onViewportChange={nextViewport => setViewport({...nextViewport})}
>
</ReactMapGL>
</div>
</MDBCol>
<MDBCol xl='4' md='12'>
Other stuff
</MDBCol>
</MDBRow>
</MDBContainer>
)
}
export default Mapas
我正在使用这个钩子来测量 div 组件 (https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node) 的大小:
function useClientRect() {
const [rect, setRect] = React.useState(null);
const ref = React.useCallback(node => {
if (node !== null) {
setRect(node.getBoundingClientRect());
}
}, []);
return [rect, ref];
}
这是我的组件,经过简化。我将它与 React Map GL 一起使用,因为无法根据 % 设置视口的宽度。我找不到其他方法...getBoundsForPoints 是一个函数,用于获取地图视口的限制,给定坐标数组和以像素为单位的地图宽度。
function Mapas(props){
const [rect,ref] = useClientRect()
useEffect(()=>{
const coordinates = [some coordinates]
let new_viewport
if (rect!==null){ //Here is when sometimes I get rect===null
new_viewport = getBoundsForPoints(coordinates, rect.width)
} else {
new_viewport = getBoundsForPoints(coordinates, 500)
}
setViewport(new_viewport)
},[rect])
return (
<MDBContainer>
<MDBRow>
<MDBCol md='12' xl='8'>
<div ref={ref}> {/*Elemento referenciado */}
<ReactMapGL
{...viewport}
mapboxApiAccessToken='xxx'}
mapStyle='xxx'
onViewportChange={nextViewport => setViewport({...nextViewport})}
>
</ReactMapGL>
</div>
</MDBCol>
<MDBCol xl='4' md='12'>
Other stuff
</MDBCol>
</MDBRow>
</MDBContainer>
)
}
export default Mapas
页面加载后工作正常;然而,当我从其他组件到达页面时,没有重新渲染,rect 为空。我怎样才能避免这种情况,谢谢!
import ResizeObserver from 'resize-observer-polyfill';
const measureSize = el => {
return {
height: el && el.current && Math.round(el.current.getBoundingClientRect().height),
width: el && el.current && Math.round(el.current.getBoundingClientRect().width),
};
};
const [size, setSize] = useState(measureSize(ref));
useEffect(() => {
setSize(measureSize(ref));
const observer = new ResizeObserver(() => {
window.requestAnimationFrame(() => {
setSize(measureSize(ref));
});
});
observer.observe(ref.current);
return () => {
observer.disconnect();
};
}, [ref]);
我使用 polyfill resize-observer-polyfill
以获得更强大的解决方案
我终于不得不使用钩子 useLayoutEffect,而不是 useEffect。钩子 (https://es.reactjs.org/docs/hooks-reference.html#uselayouteffect) 与 useEffect 类似,但在构建所有组件后是 运行,因此引用现在已正确定义并且可以测量组件的尺寸。 最终的简化代码如下:
function useClientRect() {
const [rect, setRect] = React.useState(null);
const ref = React.useCallback(node => {
console.log('Node')
console.log(node)
if (node !== null) {
setRect(node.getBoundingClientRect());
}
}, []);
return [rect, ref];
}
function Mapas(props){
const [rect,ref] = useClientRect()
useLayoutEffect(()=>{
const coordinates = [some coordinates]
let new_viewport
if (rect!==null){ //Here is when sometimes I get rect===null
new_viewport = getBoundsForPoints(coordinates, rect.width)
} else {
new_viewport = getBoundsForPoints(coordinates, 500)
}
setViewport(new_viewport)
},[rect])
return (
<MDBContainer>
<MDBRow>
<MDBCol md='12' xl='8'>
<div ref={ref}> {/*Elemento referenciado */}
<ReactMapGL
{...viewport}
mapboxApiAccessToken='xxx'}
mapStyle='xxx'
onViewportChange={nextViewport => setViewport({...nextViewport})}
>
</ReactMapGL>
</div>
</MDBCol>
<MDBCol xl='4' md='12'>
Other stuff
</MDBCol>
</MDBRow>
</MDBContainer>
)
}
export default Mapas