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

如何在ReactJS中获得视口高度?在正常的JavaScript中使用

window.innerHeight()

但是使用ReactJS,我不确定如何获得这些信息。我的理解是

ReactDOM.findDomNode()

仅适用于已创建的组件。然而,对于documentbody元素则不是这样,它们可以为我提供窗口的高度。

555805 次浏览

使用钩子(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来获取当前视口的高度。

正如你可以看到在这里

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...
}
}

设置道具

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


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

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

这个答案与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 });
}

你也可以试试这个:

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


componentWillMount(){
console.log("WINDOW : ",window);
this.setState({height: window.innerHeight + 'px',width:window.innerWidth+'px'});
}


render() {
console.log("VIEW : ",this.state);
}

我刚刚花了一些认真的时间用React和滚动事件/位置来解决一些问题-所以对于那些仍然在寻找的人,这里是我发现的:

视口高度可以通过使用window来找到。innerHeight或使用document.documentElement.clientHeight。(当前视口高度)

整个文档(主体)的高度可以使用window.document.body.offsetHeight找到。

如果你试图找到文档的高度,并知道什么时候你已经触底了——下面是我想到的:

if (window.pageYOffset >= this.myRefII.current.clientHeight && Math.round((document.documentElement.scrollTop + window.innerHeight)) < document.documentElement.scrollHeight - 72) {
this.setState({
trueOrNot: true
});
} else {
this.setState({
trueOrNot: false
});
}
}

(我的导航条在固定位置是72px,因此-72得到一个更好的滚动事件触发器)

最后,这里有一些到console.log()的滚动命令,这些命令帮助我积极地计算数学。

console.log('window inner height: ', window.innerHeight);


console.log('document Element client hieght: ', document.documentElement.clientHeight);


console.log('document Element scroll hieght: ', document.documentElement.scrollHeight);


console.log('document Element offset height: ', document.documentElement.offsetHeight);


console.log('document element scrolltop: ', document.documentElement.scrollTop);


console.log('window page Y Offset: ', window.pageYOffset);


console.log('window document body offsetheight: ', window.document.body.offsetHeight);

唷!希望它能帮助到一些人!

@speckledcarp的回答很好,但是如果你需要在多个组件中使用这个逻辑,那么可能会很乏味。您可以将其重构为HOC(高阶分量),以使此逻辑更易于重用。

withWindowDimensions.jsx

import React, { Component } from "react";


export default function withWindowDimensions(WrappedComponent) {
return class extends Component {
state = { width: 0, height: 0 };


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


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


updateWindowDimensions = () => {
this.setState({ width: window.innerWidth, height: window.innerHeight });
};


render() {
return (
<WrappedComponent
{...this.props}
windowWidth={this.state.width}
windowHeight={this.state.height}
isMobileSized={this.state.width < 700}
/>
);
}
};
}

然后在你的主组件中:

import withWindowDimensions from './withWindowDimensions.jsx';


class MyComponent extends Component {
render(){
if(this.props.isMobileSized) return <p>It's short</p>;
else return <p>It's not short</p>;
}


export default withWindowDimensions(MyComponent);

你也可以“堆叠”hoc,如果你有另一个你需要使用的hoc,例如withRouter(withWindowDimensions(MyComponent))

编辑:我现在会用React钩子(上面的例子),因为他们解决了一些hoc和职业的高级问题

@speckledcarp和@Jamesl的回答都很精彩。然而,在我的例子中,我需要一个组件,其高度可以扩展整个窗口高度,在呈现时有条件....但是在render()中调用HOC会重新渲染整个子树。很糟糕。

另外,我对获取作为道具的值不感兴趣,而只是想要一个父div,它将占据整个屏幕的高度(或宽度,或两者)。

所以我写了一个父组件,提供了一个完整的高度(和/或宽度)div。

一个用例:

class MyPage extends React.Component {
render() {
const { data, ...rest } = this.props


return data ? (
// My app uses templates which misbehave badly if you manually mess around with the container height, so leave the height alone here.
<div>Yay! render a page with some data. </div>
) : (
<FullArea vertical>
// You're now in a full height div, so containers will vertically justify properly
<GridContainer justify="center" alignItems="center" style=\{\{ height: "inherit" }}>
<GridItem xs={12} sm={6}>
Page loading!
</GridItem>
</GridContainer>
</FullArea>
)

下面是这个组件:

import React, { Component } from 'react'
import PropTypes from 'prop-types'


class FullArea extends Component {
constructor(props) {
super(props)
this.state = {
width: 0,
height: 0,
}
this.getStyles = this.getStyles.bind(this)
this.updateWindowDimensions = this.updateWindowDimensions.bind(this)
}


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


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


getStyles(vertical, horizontal) {
const styles = {}
if (vertical) {
styles.height = `${this.state.height}px`
}
if (horizontal) {
styles.width = `${this.state.width}px`
}
return styles
}


updateWindowDimensions() {
this.setState({ width: window.innerWidth, height: window.innerHeight })
}


render() {
const { vertical, horizontal } = this.props
return (
<div style={this.getStyles(vertical, horizontal)} >
{this.props.children}
</div>
)
}
}


FullArea.defaultProps = {
horizontal: false,
vertical: false,
}


FullArea.propTypes = {
horizontal: PropTypes.bool,
vertical: PropTypes.bool,
}


export default FullArea

我刚刚编辑了回城目前的答案来支持苏维埃社会主义共和国,并将其与Next.js .js (React 16.8.0+)一起使用:

/钩/ 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;
}

/ yourComponent.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>
);
}
// just use (useEffect). every change will be logged with current value
import React, { useEffect } from "react";


export function () {
useEffect(() => {
window.addEventListener('resize', () => {
const myWidth  = window.innerWidth;
console.log('my width :::', myWidth)
})
},[window])


return (
<>
enter code here
</>
)
}

美好的一天,

我知道我来晚了,但让我告诉你我的答案。

const [windowSize, setWindowSize] = useState(null)


useEffect(() => {
const handleResize = () => {
setWindowSize(window.innerWidth)
}


window.addEventListener('resize', handleResize)


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

欲了解更多详情,请访问https://usehooks.com/useWindowSize/

用一点打字稿

import { useState, useEffect } from 'react';


interface WindowDimentions {
width: number;
height: number;
}


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


return {
width,
height
};
}
  

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

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

window.addEventListener('resize', handleResize);


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

return windowDimensions;
}

我发现了一个简单的组合QoP和speckledcarp的答案,使用React Hooks和调整大小功能,代码行数略少:

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事件是双引号,而不是单引号。这一点让我有点不安;)

添加这个是为了多样性和干净的方法。

此代码使用函数式方法。我已经使用onresize而不是addEventListener,如在其他答案中提到的。

import { useState, useEffect } from "react";


export default function App() {
const [size, setSize] = useState({
x: window.innerWidth,
y: window.innerHeight
});
const updateSize = () =>
setSize({
x: window.innerWidth,
y: window.innerHeight
});
useEffect(() => (window.onresize = updateSize), []);
return (
<>
<p>width is : {size.x}</p>
<p>height is : {size.y}</p>
</>
);
}

保持当前尺寸状态的简单方法,即使在窗口调整大小后:

//set up defaults on page mount
componentDidMount() {
this.state = { width: 0, height: 0 };
this.getDimensions();


//add dimensions listener for window resizing
window.addEventListener('resize', this.getDimensions);
}


//remove listener on page exit
componentWillUnmount() {
window.removeEventListener('resize', this.getDimensions);
}


//actually set the state to the window dimensions
getDimensions = () => {
this.setState({ width: window.innerWidth, height: window.innerHeight });
console.log(this.state);
}

使用useEffect很简单

useEffect(() => {
window.addEventListener("resize", () => {
updateDimention({
...dimension,
width: window.innerWidth,
height: window.innerHeight
});
console.log(dimension);
})
})

作为回答从:bren,但挂钩useEffect到[window.innerWidth]

const [dimension, updateDimention] = useState();
  

useEffect(() => {
window.addEventListener("resize", () => {
updateDimention({
...dimension,
width: window.innerWidth,
height: window.innerHeight
});
       

})
},[window.innerWidth]);


console.log(dimension);

React原生web有一个useWindowDimensions钩子,可以使用:

    import { useWindowDimensions } from "react-native";
const dimensions = useWindowDimensions()

这是你如何实现它,并在React函数组件中实时获得窗口宽度和高度:

import React, {useState, useEffect} from 'react'
const Component = () => {
const [windowWidth, setWindowWidth] = useState(0)
const [windowHeight, setWindowHeight] = useState(0)
  

useEffect(() => {
window.addEventListener('resize', e => {
setWindowWidth(window.innerWidth);
});
}, [window.innerWidth]);


useEffect(() => {
window.addEventListener('resize', e => {
setWindowHeight(window.innerHeight);
});
}, [window.innerHeight]);


return(
<h3>Window width is: {windowWidth} and Height: {windowHeight}</h3>
)
}

使用钩子:

使用useLayoutEffect在这里是更高效的:

import { useState, useLayoutEffect } from 'react';


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


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


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


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


return windowDimensions;
}

用法:

const { height, width } = useWindowDimensions();

我通过在useCallback中包装getWindowDimensions函数更新了代码,略有变化

import { useCallback, useLayoutEffect, useState } from 'react';


export default function useWindowDimensions() {


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


const getWindowDimensions = useCallback(() => {
const windowWidth = hasWindow ? window.innerWidth : null;
const windowHeight = hasWindow ? window.innerHeight : null;


return {
windowWidth,
windowHeight,
};
}, [hasWindow]);


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


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


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


return windowDimensions;
}

你可以像这样创建自定义钩子

import { useEffect, useState } from "react";
import { debounce } from "lodash";


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


export function useWindowSize(delay = 0) {
const [windowDimensions, setWindowDimensions] = useState(
getWindowDimensions()
);


useEffect(() => {
function handleResize() {
setWindowDimensions(getWindowDimensions());
}
const debouncedHandleResize = debounce(handleResize, delay);
window.addEventListener("resize", debouncedHandleResize);
return () => window.removeEventListener("resize", debouncedHandleResize);
}, [delay]);


return windowDimensions;
}

在这里,您可以将投票次数最多的答案包装在一个节点包中(已测试,typescript),以便使用。

安装:

npm i @teambit/toolbox.react.hooks.get-window-dimensions

用法:

import React from 'react';
import { useWindowDimensions } from '@teambit/toolbox.react.hooks.get-window-dimensions';


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


return (
<>
<h1>Window size</h1>
<p>Height: {height}</p>
<p>Width: {width}</p>
</>
);
};

有一个包有93.000+下载,名为useWindowSize()

npm i @react-hook/window-size

import {
useWindowSize,
useWindowWidth,
useWindowHeight,
} from '@react-hook/window-size'


const Component = (props) => {
const [width, height] = useWindowSize()
const onlyWidth = useWindowWidth()
const onlyHeight = useWindowHeight()
...
}

docs

@foad abdollahi和@giovannipds答案的组合帮助我找到了一个解决方案,使用Nextjs中的useLayoutEffect自定义挂钩。

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


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


useLayoutEffect(() => {
const isWindow = typeof window !== 'undefined';
function handleResize() {
setWindowDimensions(getWindowDimensions());
}


isWindow && window.addEventListener('resize', handleResize);
console.log(windowDimensions);
return () =>
isWindow && window.removeEventListener('resize', handleResize);
}, [windowDimensions]);


return windowDimensions;
}