如何获得react元素的宽度

IT技术 reactjs
2021-04-12 04:45:59

我试图创建一个范围输入,在滑块拇指正上方显示一个工具提示。

我在网上浏览了一些普通的 JS 示例,似乎我需要元素的宽度来完成它。

所以我只是想知道如何获得元素宽度?

几乎等同于 JQuery 方法 $(element).width()

6个回答
    class MyComponent extends Component {
      constructor(props){
        super(props)
        this.myInput = React.createRef()
      }

      componentDidMount () {
        console.log(this.myInput.current.offsetWidth)
      }

      render () {
        return (
        // new way - as of React@16.3
        <div ref={this.myInput}>some elem</div>
        // legacy way
        // <div ref={(ref) => this.myInput = ref}>some elem</div>
        )
      }
    }
您想获取 Div 元素的宽度是什么 id,该元素是 React 元素而不是原生 html 元素?
2021-05-24 04:45:59
感谢您维护“传统”方式。
2021-06-07 04:45:59
我只想说,显然这种创建 refs 的方式现在也被弃用了。(现在您在构造函数中创建了一个 ref React.createRef()
2021-06-16 04:45:59
@aaaidan 刚刚检查了文档。回调引用没有被弃用。有时,当您不想覆盖克隆元素上的 ref 时,您需要它们。
2021-06-18 04:45:59

钩子

const MyComponent = () => {
  const ref = useRef(null);
  useEffect(() => {
    console.log('width', ref.current ? ref.current.offsetWidth : 0);
  }, [ref.current]);
  return <div ref={ref}>Hello</div>;
};
我会切换到useLayoutEffect,或者, [ref.current]完全跳过(让它更新每个渲染),或者添加一个ResizeObserver或一些东西来更新调整大小。
2021-05-26 04:45:59
而不是使用两个useRefuseEffect你可以简单地在上面的例子中使用回调REF。
2021-05-30 04:45:59
但它不会在任何调整大小发生时更新,只是当你的 ref.current 发生变化时
2021-06-14 04:45:59
Eslint 说:React Hook useEffect 有一个不必要的依赖:'ref.current'。排除它或删除依赖项数组。像 'ref.current' 这样的可变值不是有效的依赖项,因为改变它们不会重新渲染组件。
2021-06-18 04:45:59
这工作完美。另外,使用 Typescript 只需添加const ref = useRef<HTMLHeadingElement>(null);
2021-06-19 04:45:59

这基本上是 Marco Antônio 对 React 自定义挂钩的回答,但经过修改以最初设置尺寸,而不仅仅是在调整大小之后。

export const useContainerDimensions = myRef => {
  const getDimensions = () => ({
    width: myRef.current.offsetWidth,
    height: myRef.current.offsetHeight
  })

  const [dimensions, setDimensions] = useState({ width: 0, height: 0 })

  useEffect(() => {
    const handleResize = () => {
      setDimensions(getDimensions())
    }

    if (myRef.current) {
      setDimensions(getDimensions())
    }

    window.addEventListener("resize", handleResize)

    return () => {
      window.removeEventListener("resize", handleResize)
    }
  }, [myRef])

  return dimensions;
};

以同样的方式使用:

const MyComponent = () => {
  const componentRef = useRef()
  const { width, height } = useContainerDimensions(componentRef)

  return (
    <div ref={componentRef}>
      <p>width: {width}px</p>
      <p>height: {height}px</p>
    <div/>
  )
}

实际上,最好在自定义 hook 中隔离此调整大小逻辑您可以像这样创建自定义钩子:

const useResize = (myRef) => {
  const [width, setWidth] = useState(0)
  const [height, setHeight] = useState(0)

  useEffect(() => {
    const handleResize = () => {
      setWidth(myRef.current.offsetWidth)
      setHeight(myRef.current.offsetHeight)
    }

    window.addEventListener('resize', handleResize)

    return () => {
      window.removeEventListener('resize', handleResize)
    }
  }, [myRef])

  return { width, height }
}

然后你可以像这样使用它:

const MyComponent = () => {
  const componentRef = useRef()
  const { width, height } = useResize(componentRef)

  return (
    <div ref={myRef}>
      <p>width: {width}px</p>
      <p>height: {height}px</p>
    <div/>
  )
}
您必须将调整大小事件侦听器附加到我认为的窗口:developer.mozilla.org/en-US/docs/Web/API/Window/resize_event
2021-06-03 04:45:59
handleResize() 在 EventListeners 上,否则 useResize 将返回 { 0, 0}
2021-06-14 04:45:59
不返回初始大小。即仅在调整大小后才有效。修复useResize需要包括`if (myRef.current) {<setWidth SetHeight etc,>)
2021-06-15 04:45:59

一个简单且最新的解决方案是使用 React React useRef钩子,该钩子存储对组件/元素的引用,结合useEffect钩子,在组件渲染时触发。

import React, {useState, useEffect, useRef} from 'react';

export default App = () => {
  const [width, setWidth] = useState(0);
  const elementRef = useRef(null);

  useEffect(() => {
    setWidth(elementRef.current.getBoundingClientRect().width);
  }, []); //empty dependency array so it only runs once at render

  return (
    <div ref={elementRef}>
      {width}
    </div>
  )
}
它不是 getBoundingRect,而是 getBoundingClientRect()
2021-05-25 04:45:59
这意味着由于某种原因,ref 在第一次渲染时没有被绑定到元素。一个简单的解决方法是if (!ref.current) return;在使用 ref 之前添加,并将 ref 添加到依赖项数组,这样它看起来就像[ref]一个空数组
2021-06-02 04:45:59
我得到 columnRef.current.getBoundingRect 不是一个函数
2021-06-14 04:45:59