ReactJS에서 뷰포트 / 창 높이 가져 오기


160

ReactJS에서 뷰포트 높이를 어떻게 얻습니까? 일반적인 JavaScript에서는

window.innerHeight()

그러나 ReactJS를 사용하면이 정보를 얻는 방법을 모르겠습니다. 내 이해는

ReactDOM.findDomNode()

생성 된 컴포넌트에만 작동합니다. 그러나 이것은 document또는 body요소 의 경우가 아니므로 창의 높이를 얻을 수 있습니다.

답변:


245

이 답변은 창 크기 조정도 처리한다는 점을 제외하고 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 });
}

3
.bind(this)콜백 인수는 이미 생성자에 의해 바인딩되어 있으므로 제거 할 수 있습니다 .
Scymex

1
Nitpick : 생성자의 코드는 아마도 this.state = { width: 0, height: 0 };상태 변수가 유형을 변경하지 않도록해야합니다 ( window.innerWidth가 integer 인 경우 ). IMHO를 이해하기 쉽게 코드를 제외하고는 아무것도 변경하지 않습니다. 답변 해주셔서 감사합니다!
johndodo

1
@johndodo. 으악. 편집했습니다.
speckledcarp

7
this.state = { width: window.innerWidth, height: window.innerHeight };시작 하지 않습니까?
Gerbus

1
콜백을 사용하여 창의 크기 조정 이벤트를 대상으로 한 다음 콜백 내에서 전역 창 개체를 다시 대상으로 지정하는 것이 가장 좋은 방법은 아닙니다. 성능, 가독성 및 컨벤션을 위해 주어진 이벤트 값을 사용하도록 업데이트하겠습니다.
GoreDefex

177

후크 사용 (반응 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하며 현재 뷰포트의 높이를 얻는 데 사용할 수 있습니다 .

여기서 볼 수 있듯이


2
window.innerHeight는 함수가 아니라 속성입니다
Jairo

2
Kevin Danikowski가 답변을 수정 한 것으로 보이며 변경이 승인되었습니다. 이제 수정되었습니다.
QoP

3
@FeCH 컴포넌트를 마운트 해제 할 때 이벤트 리스너를 제거합니다. 그것은 cleanup함수 라고 불립니다. 여기서
QoP

1
SSR (NextJS)과 동일한 접근 방식을 얻는 아이디어가 있습니까?
roadev

1
NextJS의 @roadev에서 req소품을 사용할 수 있는지 확인할 수도 있습니다 getInitialProps. 그렇다면 서버에서 실행중인 경우 창 변수가 없습니다.
giovannipds

54
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}로 사용할 수 있습니다.


13
브라우저 창의 크기가 변경되면이 솔루션은 업데이트되지 않습니다.
speckledcarp

1
참고로, 컴포넌트 마운트 후 상태를 업데이트하면 두 번째 render () 호출이 트리거되어 속성 / 레이아웃 스 래싱이 발생할 수 있습니다. github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/…
Haukur Kristinsson

1
@HaukurKristinsson 이걸 극복하는 방법?
Richard

1
@JabranSaeed 왜 마운트에서 업데이트하는 대신 생성자에서 높이를 설정하지 않겠습니까? 소품을 고려해야 할 경우 다음과 같이 기본값을 지정할 수 있습니다 height: window.innerHeight || props.height. 이것은 코드를 단순화 할뿐만 아니라 불필요한 상태 변경을 제거합니다.
JohnnyQ

componentWillMount더 이상 권장하지 않습니다. reactjs.org/docs/react-component.html#unsafe_componentwillmount
holmberd

26

방금 SSR 을 지원 하고 Next.js 와 함께 사용 하기 위해 QoP현재 답변 을 편집 했습니다 (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>
  );
}

훌륭한 솔루션.
Jeremy E

NextJS 로이 작업을 시도했지만 화면 크기 조정 후 크기가 올바른 것 같습니다. nextJS 서버 측 렌더링 때문이라고 가정합니다. 당신은 어떤 아이디어가 있습니까?
herohamp

15

@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를 "스택"할 수도 있습니다. withRouter(withWindowDimensions(MyComponent))

편집 : HOC 및 클래스와 관련된 고급 문제 중 일부를 해결하기 위해 요즘 React 후크 ( 위의 예 )를 사용합니다.


1
좋은 작업 @ 제임스
마니 샤르마

8

나는 방금 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);

아휴! 그것이 누군가를 돕기를 바랍니다!


3
// 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
   </>
  )
}

1
스택 오버플로에 오신 것을 환영합니다. 설명이없는 코드 덤프는 거의 도움이되지 않습니다. 스택 오버플로는 맹목적으로 복사하여 붙여 넣을 스 니펫을 제공하지 않고 학습에 관한 것입니다. 제발 편집 질문을하고 영업 이익이 제공하는 것보다 더 잘 작동 방법을 설명합니다.
Chris

2

@speckledcarp와 @Jamesl의 답변은 훌륭합니다. 그러나 내 경우에는 렌더링 시간에 조건부로 높이가 전체 창 높이를 확장 할 수있는 구성 요소가 필요했지만 HOC를 호출 render()하면 전체 하위 트리가 다시 렌더링됩니다. BAAAD.

또한 값을 소품으로 가져 오는 데 관심이 없었지만 div전체 화면 높이 (또는 너비 또는 둘 다)를 차지하는 부모 를 원했습니다 .

그래서 전체 높이 (또는 너비) div를 제공하는 Parent 구성 요소를 작성했습니다. 팔.

사용 사례 :

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

0

당신은 또한 이것을 시도 할 수 있습니다 :

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);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.