在 ReactJS 中获取视口/窗口高度

IT技术 javascript reactjs window viewport
2021-01-21 07:51:43

如何在 ReactJS 中获取视口高度?在普通的 JavaScript 中,我使用

window.innerHeight()

但是使用 ReactJS,我不确定如何获取此信息。我的理解是

ReactDOM.findDomNode()

仅适用于创建的组件。然而,这不是documentorbody元素的情况,它可以给我窗口的高度。

6个回答

使用钩子 (React 16.8.0+)

创建一个useWindowDimensions钩子。

import { useState, useEffect } from 'react';

function getWindowDimensions() {
  const { innerWidth: width, innerHeight: height } = window;
  return {
    width,
    height
  };
}

export default function useWindowDimensions() {
  const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());

  useEffect(() => {
    function handleResize() {
      setWindowDimensions(getWindowDimensions());
    }

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return windowDimensions;
}

之后你就可以像这样在你的组件中使用它

const Component = () => {
  const { height, width } = useWindowDimensions();

  return (
    <div>
      width: {width} ~ height: {height}
    </div>
  );
}

工作示例

原答案

在 React 中也是如此,您可以使用它window.innerHeight来获取当前视口的高度。

正如你在这里看到的

写得这么好的答案。希望更多的人写这样的 stackoverflow 答案而不是发布 npm module。
2021-03-13 07:51:43
@FeCH 它在卸载组件时删除事件侦听器。它被称为cleanup函数,你可以在这里阅读它
2021-03-19 07:51:43
看起来 Kevin Danikowski 编辑了答案,并且以某种方式批准了该更改。现在已经修好了。
2021-03-24 07:51:43
window.innerHeight 不是一个函数,它是一个属性
2021-03-26 07:51:43
使用 SSR (NextJS) 获得相同方法的任何想法?
2021-04-07 07:51:43

这个答案类似于 Jabran Saeed 的,除了它也处理窗口大小调整。我从这里得到的

constructor(props) {
  super(props);
  this.state = { width: 0, height: 0 };
  this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
}

componentDidMount() {
  this.updateWindowDimensions();
  window.addEventListener('resize', this.updateWindowDimensions);
}

componentWillUnmount() {
  window.removeEventListener('resize', this.updateWindowDimensions);
}

updateWindowDimensions() {
  this.setState({ width: window.innerWidth, height: window.innerHeight });
}
也许这不是最好的主意,使用回调来定位窗口的调整大小事件,然后在回调中重新定位全局窗口对象。出于性能、可读性和约定的考虑,我将更新它以使用给定的事件值。
2021-03-18 07:51:43
您可以.bind(this)从回调参数中删除,因为它已经被构造函数绑定了。
2021-03-21 07:51:43
@格布斯:+1。这就是它在初始页面加载时对我有用的原因。
2021-03-24 07:51:43
为什么不this.state = { width: window.innerWidth, height: window.innerHeight };开始?
2021-03-29 07:51:43
挑剔:构造函数中的代码可能应该是this.state = { width: 0, height: 0 };状态变量不会改变它们的类型(如果我理解正确的话window.innerWidth 是 integer)。除了让代码更容易理解恕我直言之外,不会改变任何东西。谢谢你的回答!
2021-04-03 07:51:43
class AppComponent extends React.Component {

  constructor(props) {
    super(props);
    this.state = {height: props.height};
  }

  componentWillMount(){
    this.setState({height: window.innerHeight + 'px'});
  }

  render() {
    // render your component...
  }
}

设置props

AppComponent.propTypes = {
 height:React.PropTypes.string
};

AppComponent.defaultProps = {
 height:'500px'
};

视口高度现在可用作渲染模板中的 {this.state.height}

如果调整浏览器窗口大小,此解决方案不会更新
2021-03-15 07:51:43
2021-03-19 07:51:43
@HaukurKristinsson 如何克服这个问题?
2021-03-23 07:51:43
仅供参考,在组件安装后更新状态将触发第二次 render() 调用,并可能导致属性/布局抖动。github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/...
2021-03-29 07:51:43
@JabranSaeed 为什么不直接在构造函数上设置高度而不是在安装时更新它?如果你需要的道具考虑您可以默认这样的value给它:height: window.innerHeight || props.height这不仅会简化代码,还会删除不必要的状态更改。
2021-03-30 07:51:43

我刚刚编辑了QoP当前答案以支持SSR并将其与Next.js (React 16.8.0+) 一起使用:

/hooks/useWindowDimensions.js

import { useState, useEffect } from 'react';

export default function useWindowDimensions() {

  const hasWindow = typeof window !== 'undefined';

  function getWindowDimensions() {
    const width = hasWindow ? window.innerWidth : null;
    const height = hasWindow ? window.innerHeight : null;
    return {
      width,
      height,
    };
  }

  const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());

  useEffect(() => {
    if (hasWindow) {
      function handleResize() {
        setWindowDimensions(getWindowDimensions());
      }

      window.addEventListener('resize', handleResize);
      return () => window.removeEventListener('resize', handleResize);
    }
  }, [hasWindow]);

  return windowDimensions;
}

/你的组件.js

import useWindowDimensions from './hooks/useWindowDimensions';

const Component = () => {
  const { height, width } = useWindowDimensions();
  /* you can also use default values or alias to use only one prop: */
  // const { height: windowHeight = 480 } useWindowDimensions();

  return (
    <div>
      width: {width} ~ height: {height}
    </div>
  );
}
这个答案不起作用,因为它不会在不调整大小的情况下设置大小。看到我之前的评论请进行编辑
2021-03-14 07:51:43
@giovannipds 抱歉,我一定是误读了它,这是有效的
2021-03-22 07:51:43
很好的解决方案。
2021-03-25 07:51:43
嗨乔瓦尼,谢谢你的回答。是的,我明白你的代码在做什么。我的观点是向其他人表明,使用 Next 的最新版本会触发警告(我同意你的看法,它仍然有效,这只是一个警告)。我无法在文档中的任何地方找到以下方法: 1. 在 Next 中轻松忽略此警告。2. 调整代码,使其不会触发它。稍后,如果您有任何指示,请告诉我;-)
2021-04-01 07:51:43
我尝试使用 NextJS 执行此操作,但在屏幕调整大小后似乎只有正确的大小。我认为这是因为 nextJS 服务器端渲染。你有什么想法?
2021-04-04 07:51:43

我使用 React Hooks 和调整大小功能找到了 QoP 和 spekledcarp 的答案的简单组合,代码行数略少:

const [width, setWidth]   = useState(window.innerWidth);
const [height, setHeight] = useState(window.innerHeight);
const updateDimensions = () => {
    setWidth(window.innerWidth);
    setHeight(window.innerHeight);
}
useEffect(() => {
    window.addEventListener("resize", updateDimensions);
    return () => window.removeEventListener("resize", updateDimensions);
}, []);

哦,是的,确保resize事件是双引号,而不是单引号。那个让我有点;)

单引号有什么问题?
2021-03-17 07:51:43