如何在ReactJS中获得视口高度?在正常的JavaScript中使用
window.innerHeight()
但是使用ReactJS,我不确定如何获得这些信息。我的理解是
ReactDOM.findDomNode()
仅适用于已创建的组件。然而,对于文档或body元素,情况并非如此,它们可以为我提供窗口的高度。
如何在ReactJS中获得视口高度?在正常的JavaScript中使用
window.innerHeight()
但是使用ReactJS,我不确定如何获得这些信息。我的理解是
ReactDOM.findDomNode()
仅适用于已创建的组件。然而,对于文档或body元素,情况并非如此,它们可以为我提供窗口的高度。
当前回答
@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
其他回答
美好的一天,
我知道我来晚了,但让我告诉你我的答案。
const [windowSize, setWindowSize] = useState(null)
useEffect(() => {
const handleResize = () => {
setWindowSize(window.innerWidth)
}
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])
欲了解更多详情,请访问https://usehooks.com/useWindowSize/
这个答案与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 });
}
有一个包有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
你可以像这样创建自定义钩子:
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的回答很好,但是如果你需要在多个组件中使用这个逻辑,那么可能会很乏味。您可以将其重构为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,如果你有另一个你需要使用,例如withthrouter (withWindowDimensions(MyComponent))
编辑:我现在会用React钩子(上面的例子),因为它们解决了hoc和类的一些高级问题