如何在 ReactJS 中获取视口高度?在我使用的普通 JavaScript 中
window.innerHeight()
但是使用 ReactJS,我不确定如何获取这些信息。我的理解是
ReactDOM.findDomNode()
仅适用于创建的组件。但是,对于 document
或 body
元素,情况并非如此,这可能会给我窗口的高度。
使用 Hooks (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
来获取当前视口的高度。
如您所见here
这个答案类似于 Jabran Saeed 的,除了它也处理窗口大小调整。我从 here 得到的。
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 });
}
.bind(this)
,因为它已经被构造函数绑定。
this.state = { width: 0, height: 0 };
,这样状态变量就不会改变它们的类型(如果我理解正确的话 window.innerWidth is integer)。除了使代码更容易理解恕我直言之外,不会改变任何东西。感谢你的回答!
this.state = { width: window.innerWidth, height: window.innerHeight };
开始?
我刚刚编辑了 QoP 的 current answer 以支持 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;
}
/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>
);
}
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}
height: window.innerHeight || props.height
。这不仅会简化代码,还会消除不必要的状态更改。
componentWillMount
,请参阅 reactjs.org/docs/react-component.html#unsafe_componentwillmount
我使用 React Hooks 和调整大小功能找到了 QoP 和斑点卡的简单组合,代码行数略少:
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
事件是双引号,而不是单引号。那个让我有点;)
window is not defined
问题?
@speckledcarp 的答案很棒,但如果您在多个组件中需要此逻辑,可能会很乏味。您可以将其重构为 HOC (higher order component) 以使此逻辑更易于重用。
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 钩子(example above here),因为它们解决了一些 advanced issues with HOCs and classes
用一点打字稿
从“反应”导入 { useState, useEffect };界面 WindowDimentions { 宽度:数字;高度:数字; } function getWindowDimensions(): WindowDimentions { const { innerWidth: width, innerHeight: height } = window;返回{宽度,高度}; } 导出默认函数 useWindowDimensions(): WindowDimentions { const [windowDimensions, setWindowDimensions] = useState
添加这个以实现多样性和干净的方法。
此代码使用功能样式方法。如其他答案中所述,我使用了 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>
</>
);
}
我只是花了一些时间用 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);
哇!希望它可以帮助某人!
使用钩子:
在这里使用 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();
再会,
我知道我参加这个聚会迟到了,但让我告诉你我的答案。
const [windowSize, setWindowSize] = useState(null)
useEffect(() => {
const handleResize = () => {
setWindowSize(window.innerWidth)
}
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])
有关详细信息,请访问 https://usehooks.com/useWindowSize/
// 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
</>
)
}
您可以像这样创建自定义挂钩:useWindowSize()
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;
}
@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
通过将 getWindowDimensions 函数包装在 useCallback 中,我更新了代码稍有变化
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;
}
这是您可以实现它并在 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>
)
}
你也可以试试这个:
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);
}
即使在调整窗口大小后,也可以将当前尺寸保持在状态的简单方法:
//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 Native Web 有一个可以使用的 useWindowDimensions 钩子:
import { useWindowDimensions } from "react-native";
const dimensions = useWindowDimensions()
在这里,您可以将投票最多的答案包装在一个节点包(经过测试,打字稿)中,以供使用。
安装:
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>
</>
);
};
不定期副业成功案例分享
cleanup
函数,您可以阅读它here