6

我有一个纯粹用功能组件构建的反应应用程序。我想在屏幕上呈现元素后获取元素的高度,以相应地更改其父级的大小。

有基于类的应用程序的解决方案,但我找不到任何功能组件。

我从答案中尝试了这个解决方案,但它没有运行 useEffect 钩子

这是从我的组件中提取的代码

import React, {useRef, useEffect} from 'react';
import {
    MenuContainer,
    GrayBox,
    Wrapper

} from '../LayersMenu/LayerMenu.styles';


export const Component = ({ category, showStatistics }) => {
    const grayBoxRef= useRef(null);
    const wrapperRef= useRef(null);
    const testRef= useRef(null);
    useEffect(()=>{
        const height = wrapperRef.current.offsetHeight;
        console.log(height,'check');
      }, [wrapperRef])
    useEffect(()=>{
        const height = testRef.current.offsetHeight;
        console.log(height,'check2');
    },[testRef]);
    return (
        <MenuContainer ref={testRef}>
            <GrayBox ref={grayBoxRef}>
                <Wrapper ref={wrapperRef} hasAnyAllowedStats={showStatistics}>
                </Wrapper>
            </GrayBox>
        </MenuContainer>
    );
};

PS:接受的答案不适用于我的答案,但它适用于他在答案中添加的项目,所以我猜我的项目结构有问题或不完全确定。

非常感谢您的回答

4

2 回答 2

10

代替使用类组件,componentDidMount有一个称为钩子的钩子useEffect可以帮助您以某种方式捕获组件的渲染状态。

使用功能组件获取渲染 DOM 元素高度的解决方案如下:

 const YourComponent = () => {
   const inputRef = useRef(null);
   useEffect(() => {
      const height = inputRef.current.offsetHeight;
      console.log('Input height', height);   
   }, [inputRef]);

   return <>
     <input ref={inputRef} type="text" defaultValue="testing" />
   </>
}

解释:

useRef如文档所述,钩子将帮助您在组件的生命周期内保留对象的引用:

useRef 返回一个可变 ref 对象,其 .current 属性初始化为传递的参数 (initialValue)。返回的对象将在组件的整个生命周期内持续存在。

一旦您使用useEffectuseRef上述解决方案中的组合,您将获得预期的结果。对于useEffect钩子,文档说明:

传递给 useEffect 的函数将在渲染提交到屏幕后运行。

传递inputRef给依赖数组将在更改input元素时触发传递的函数 for useEffect。然后代码计算组件的高度,在这种情况下它只是一个input元素。这可以是任何 DOM 元素,就像div.

更新:

从您更新的问题中,解决方案是forwardRef,阅读文档:

Ref 转发是一种通过组件自动将 ref 传递给它的一个子组件的技术。

使用这种技术,您可以在父组件中访问子组件的属性,例如:内部<div><input>元素的高度,代码可用于进一步用途。

在您的子功能组件中,代码应该用于forwardRef访问内部 DOM 元素,如下所示:

import React, { forwardRef } from 'react';

// ...

const YourComponent = forwardRef((props, ref) => {
   return <>
      <input ref={ref} type="text" defaultValue="testing" />
   </>
});

然后在父组件中使用如下:

const componentRef = useRef(null);
useEffect(() => {
    const {offsetHeight} = componentRef.current;
    console.log('componentRef height', offsetHeight);   
}, [componentRef]);

return <>
    <YourComponent ref={componentRef} />
</>    

如果您有兴趣,请在此处找到文档: 将引用转发到 DOM 组件

请为您的场景找到一个有效的 GitHub 解决方案,我刚刚为表示而构建: norbitrial/react-forwarding-ref-example

希望这能给你进一步的想法。

于 2019-11-19T20:40:48.647 回答
0

使用useRef-hook:

export const SomeComponent = () => {

const divRef= useRef(null);

   useEffect(()=>{
     if(divRef.current){
     // your logic
     }
   }, [divRef])

   return(
   <div ref={divRef}></div>
   )
}
于 2019-11-19T20:28:11.380 回答