ReactJS'de görünüm / pencere yüksekliğini alma


160

ReactJS'de görünüm yüksekliğini nasıl alabilirim? Normal JavaScript’te kullanıyorum

window.innerHeight()

ancak ReactJS kullanarak bu bilgiyi nasıl alacağımdan emin değilim. Benim anlayışım şu ki

ReactDOM.findDomNode()

yalnızca oluşturulan bileşenler için çalışır. Ancak bu, pencerenin yüksekliğini bana verebilecek documentveya bodyöğesi için geçerli değildir .

Yanıtlar:


245

Bu yanıt Jabran Saeed'inkine benzer, ancak pencere yeniden boyutlandırması da ele alınır. Buradan anladım .

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)Zaten yapıcı tarafından bağlı olduğu için geri çağrı argümanlarından kaldırabilirsiniz .
Scymex

1
Nitpick: yapıcıdaki kod muhtemelen this.state = { width: 0, height: 0 };durum değişkenlerinin türlerini değiştirmemesi için olmalıdır (doğru bir şekilde window.innerWidth tamsayı ise ). Dışında hiçbir şeyi değiştirmez kod IMHO anlamak için kolaylaştırır. Cevap için teşekkürler!
johndodo

1
@johndodo. Whoops. Düzenlenen.
speckledcarp

7
Neden this.state = { width: window.innerWidth, height: window.innerHeight };başlamıyorsunuz?
Gerbus

1
Belki de pencerenin yeniden boyutlandırma olayını hedeflemek için bir geri arama kullanmak ve sonra geri arama içindeki genel pencere nesnesini yeniden hedeflemek en iyi fikir değildir. Performans, okunabilirlik ve kural uğruna, verilen olay değerlerini kullanacak şekilde güncelleyeceğim.
GoreDefex

177

Kancaların Kullanımı (Tepki 16.8.0+)

Bir useWindowDimensionskanca oluşturun .

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

Ve bundan sonra bunu böyle bileşenlerinizde kullanabilirsiniz

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

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

Çalışma örneği

Orijinal cevap

React ile aynıdır window.innerHeight, mevcut görünümün yüksekliğini elde etmek için kullanabilirsiniz .

Gördüğünüz gibi burada


2
window.innerHeight bir işlev değil, bir özellik
Jairo

2
Kevin Danikowski cevabı düzenledi ve bir şekilde bu değişiklik onaylandı. Şimdi düzeltildi.
QoP

3
@FeCH, ​​bileşenin bağlantısı kesildiğinde olay dinleyicisini kaldırır. Deniyor cleanupbu konuda okuyabilir, fonksiyon burada
qop

1
SSR (NextJS) ile aynı yaklaşımı elde etmek için herhangi bir fikriniz var mı?
roadev

1
@roadev NextJS de, aynı zamanda kontrol edebilir reqProp en uygun tarihinde adlı getInitialProps. Eğer öyleyse, sunucuda çalışıyorsa, pencere değişkenleriniz olmaz.
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...
  }
}

Destekleri ayarlayın

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

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

görüntüleme alanı yüksekliği artık oluşturma şablonunda {this.state.height} olarak kullanılabilir


13
Tarayıcı penceresi yeniden boyutlandırılırsa bu çözüm güncellenmez
speckledcarp

1
Bileşen bağlama işleminden sonra durumu güncellemek FYI, ikinci bir render () çağrısını tetikler ve özellik / mizanpajın bozulmasına neden olabilir. github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/…
Kristinsson

1
@HaukurKristinsson bunun üstesinden nasıl gelinir?
Richard

1
@JabranSaeed neden sadece devam edip montaj yerinde güncellemek yerine yapıcıdaki yüksekliği ayarlamıyorsunuz? Eğer dikkate sahne almak gerekirse böyle buna değer varsayılan edebilirsiniz: height: window.innerHeight || props.height. Bu sadece kodu basitleştirmekle kalmaz, aynı zamanda gereksiz durum değişikliklerini de kaldırır.
JohnnyQ

componentWillMountartık önerilmemektedir, bkz. reaktjs.org/docs/react-component.html#unsafe_componentwillmount
holmberd

26

Sadece kaydetmiştiniz QoP 'ın şimdiki cevabı destekleyecek SSR ve ile kullanmak Next.js (16.8.0+ tepki):

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

Harika bir çözüm.
Jeremy E

Bunu NextJS ile yapmayı denedim, ancak ekran yeniden boyutlandırıldıktan sonra sadece doğru boyuta sahip gibi görünüyor. NextJS sunucu tarafı oluşturma nedeniyle olduğunu varsayalım. Hiç fikrin var mı?
herohamp

15

@speckledcarp'ın cevabı harika, ancak bu mantığa birden fazla bileşende ihtiyacınız varsa sıkıcı olabilir. Bir olarak planı ayrı HOC (yüksek mertebeden bileşeni) yeniden bu mantık kolaylaştırmak için.

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

Sonra ana bileşeninizde:

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);

Ayrıca, kullanmanız gereken başka bir ürününüz varsa HOC'ları "istifleyebilirsiniz"; withRouter(withWindowDimensions(MyComponent))

Düzenleme: HOCs ve sınıflar ile bazı gelişmiş sorunları çözmek gibi ben bugünlerde ( burada yukarıdaki örnek ) bir React kanca ile gitmek istiyorum


1
İyi iş @James
Manish sharma

8

Ben sadece React ve olayları / pozisyonları kaydırma bazı şeyler bulmak için biraz ciddi zaman geçirdim - bu yüzden hala arayanlar için, ben ne buldum:

Görünüm yüksekliğini window.innerHeight veya document.documentElement.clientHeight kullanarak bulabilirsiniz. (Geçerli görünüm alanı yüksekliği)

Tüm belgenin (gövde) yüksekliği window.document.body.offsetHeight kullanılarak bulunabilir.

Belgenin yüksekliğini bulmaya ve dibe vurduğunuzu bilmeye çalışıyorsanız - işte burada buldum:

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
        });
      }
    }

(Gezinme çubuğum sabit konumda 72 pikseldi, böylece daha iyi bir kaydırma olayı tetikleyicisi elde etmek için -72)

Son olarak, console.log () için bir kaç kaydırma komutu var.

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);

Whew! Umarım birine yardım eder!


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
Stack Overflow'a hoş geldiniz. Herhangi bir açıklama yapmadan kod dökümleri nadiren yardımcı olur. Yığın Taşması öğrenme ile ilgilidir, körü körüne kopyalayıp yapıştırmak için parçacıklar sağlamaz. Lütfen sorunuzu düzenleyin ve OP'nin sağladığından daha iyi nasıl çalıştığını açıklayın.
Chris

2

@Speckledcarp ve @ Jamesl'in cevapları her ikisi de mükemmel. Ancak benim durumumda, yüksekliği tam pencere yüksekliğini, oluşturma zamanında koşullu olarak uzatabilecek bir bileşene ihtiyacım vardı ... ancak içinde bir HOC çağırmak render()tüm alt ağacı yeniden oluşturur. Baaad.

Ayrıca, değerleri sahne olarak almakla ilgilenmedim, ancak divtüm ekran yüksekliğini (veya genişliğini veya her ikisini) işgal edecek bir ebeveyn istedim .

Bu yüzden bir tam bileşen (ve / veya genişlik) div sağlayan bir Üst öğe yazdım. Boom.

Bir kullanım örneği:

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>
    )

İşte bileşen:

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

Bunu da deneyebilirsiniz:

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);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.