简体   繁体   English

有没有其他简单的方法可以使用 React Hooks 获取容器的高度和宽度?

[英]Is there any other easy way to get the height and width of a container using React Hooks?

I'm using React hooks useEffect to get the width and height of the container .我正在使用 React 钩子useEffect来获取container的宽度和高度。 The problems I want to solve are:我要解决的问题是:

  1. I want to get the responsive container height/width and not the window height/width.我想获得响应式容器的高度/宽度,而不是窗口的高度/宽度。
  2. My Initial state is set to window.innerHeight and this itself crashes my output on the Initial render as I'm using the dimension state to get something done in the first place.我的初始状态设置为window.innerHeight并且这本身会使我在初始渲染上的输出崩溃,因为我首先使用dimension状态来完成某些事情。
  3. I want to use the latest methods which are much simpler.. may be useRef() or anything..我想使用更简单的最新方法..可能是 useRef() 或任何东西..

I'm new to this React Hooks and unaware of many things.. I want simple code which perfectly does the work.我是这个 React Hooks 的新手,对很多事情一无所知。我想要完美地完成工作的简单代码。

My code is as below:我的代码如下:

function debounce(fn, ms) {
    let timer;
    return (_) => {
        clearTimeout(timer);
        timer = setTimeout((_) => {
            timer = null;
            fn.apply(this, arguments);
        }, ms);
    };
}

export default function App() {
    const [dimensions, setDimensions] = useState({
        height: window.innerHeight,
        width: window.innerWidth,
    });

    useEffect(() => {
        const debouncedHandleResize = debounce(function handleResize() {
            setDimensions({
                height: window.innerHeight,
                width: window.innerWidth,
            });
        }, 1000);

        document
            .getElementById('SldBox')
            .addEventListener('resize', debouncedHandleResize);

        return (_) => {
            document
                .getElementById('SldBox')
                .removeEventListener('resize', debouncedHandleResize);
        };
    });

    return (
        <div className='container' id='SldBox'>
            My Container
        </div>
    );
}

Cool problem, lots of hooks to be learned here.很酷的问题,这里有很多钩子要学习。

Here is a sample of how we can use:这是我们如何使用的示例:

  • useState使用状态
  • useEffect使用效果
  • useMemo使用备忘录
  • useRef使用参考

https://codesandbox.io/s/keen-poincare-c8mcz?file=/src/App.js https://codesandbox.io/s/keen-poincare-c8mcz?file=/src/App.js

useState : You've made good use of this one. useState :你很好地利用了这个。 No need to explain it more.无需多做解释。

useRef : Create a ref then pass it to your element. useRef :创建一个 ref 然后将其传递给您的元素。

export default function App() {
  const ref = useRef(null);

  return (
    <div ref={ref}>stuff</div>
  );
}

Now after the first render, we can reference the element easily enough.现在在第一次渲染之后,我们可以很容易地引用元素。

useMemo : To set up an observer for an element we can use ResizeObserver . useMemo :要为元素设置观察者,我们可以使用ResizeObserver If we didn't wrap this in useMemo , we would be recreating this function on every render which is wasteful.如果我们不将其包装在useMemo中,我们将在每次渲染时重新创建此函数,这是一种浪费。 useMemo remedies this. useMemo解决了这个问题。 We also add a dependency array for useMemo as the second argument that includes ref.current .我们还为ref.current useMemo第二个参数。 This way, anytime ref changes (like on the first render), the elementObserver function will be recalculated.这样,任何时候 ref 更改(例如在第一次渲染时),都会重新计算elementObserver函数。

  const elementObserver = useMemo(() => {
    return new ResizeObserver(() => {
      debounce(() => {
        if (!ref.current) return;
        setDimensions({
          height: ref.current.clientHeight,
          width: ref.current.clientWidth
        });
      }, 1000)();
    });
  }, [ref.current]);

useEffect : Now we can just use useEffect to set the observer when the component mounts. useEffect :现在我们可以在组件挂载时使用useEffect设置观察者。 Again we include a dependency array that tells the effect to trigger the callback function provided if any of these values are changed.我们再次包含一个依赖数组,它告诉效果在任何这些值发生更改时触发提供的回调函数。 It will also always run when the component mounts, so we need to check ref exists for this one.它也会在组件挂载时始终运行,因此我们需要检查 ref 是否存在。 Also, assign the element to a variable in the effect for the "cleanup" function.此外,将元素分配给“清理”功能效果中的变量。

  useEffect(() => {
    if (!ref) return;
    const element = ref.current;

    elementObserver.observe(element);
    return () => {
      elementObserver.unobserve(element);
    };
  }, [ref.current, elementObserver]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM