反应如何动态设置 div 高度以跟随包括滚动在内的完整 window 高度

React how to dynamically set div height to follow suit of full window height including scroll

我正在制作一个 React redux 应用。

我的视图随着我添加元素而变大(或随着我删除它们而变小)但是我无法让我的背景正确地跟随。

我试过使用 scrollHeight 来确定它应该具有的大小:

https://i.imgur.com/HGHJgub.gifv

这是我的代码:

constructor(props) {
    super(props);
    this.state = {
        heightSet: 0,
    };
    this.updateDimensions = this.updateDimensions.bind(this);
}

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

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

updateDimensions() {
    this.setState({ heightSet: document.body.scrollHeight });
    console.log(document.body.scrollHeight);
}

render() {
    const divStyle = {
        height: this.state.heightSet + 'px',
    };
    return (
        <div style={divStyle}>
        </div>
    )
}

但是所有这些显然都应该被抛弃。 我没有采取正确的方法。 它还涉及我的应用程序的另一个问题: 它知道向视图添加高度但不删除它。 任何人都知道为什么它有这种行为以及如何补救它?

更新:

澄清 真正的问题是,当我单击 "add component" 并且我的滚动高度增加时,此解决方案对 var 没有任何更新。 总而言之,上述解决方案完全是垃圾。 我喜欢这个想法:Set color for extra page parts visible during rubber band scroll(是的,这是一个技巧,但我觉得没问题)

来自 Shishir Arora 和 tksb

但它似乎不适用于现代浏览器(至少 Chrome 并且最新的 Chrome 是我应用程序的目标 N°1)。

我重现了这个场景,我做到了。希望对你有帮助。

Why is it always growing?

在我的例子中,document.body.scrollHeight 返回 body 的高度及其边距(出于某种原因),因此每次设置组件高度时,它始终小于 body 的 scrollHeight 并且考虑到body 随其 children 增长,随着大小的调整,组件一直在增长。

例如:

 componentDidMount : 
   bodyHeight = 90 + 10 (a margin)
   scrollHeight = 100
   componentHeight = 100

   newBodyHeight = 100 + 10 

 Resize:
   bodyHeight = 100 + 10 
   scrollHeight = 110
   componentHeight = 110

   newBodyHeight = 110 + 10 , and so on.

How to remedy it?

您可以从 scrollHeight 中减去主体的边距,或者从组件的 children 高度计算高度。

我刚刚更改了这个:

updateDimensions() {
  const margin = 16; // In my case was marginTop: 8px and marginBottom: 8px
  const heightSet = document.body.scrollHeight - margin;
  this.setState({ heightSet });
}

所以事实证明你可以只用 css 做到这一点,而且这个技巧看似简单:

在您的导航栏组件中添加:

render() {
        return (
            <Navbar>
                <div className="top-nav-white" />

                ...content

            </Navbar>
        );
    }

并在 css 中:

.top-nav-white{
  background-color: white; // (or the color you want to be overflowing)
  height: 100px;
  width: 100%;
  position: absolute;
  top: -100px;
}

这样你可以在 htmlbody 上保留背景颜色:

html{
}
body{
  height: 100vh;
  margin: 0;
  padding: 0;
  background-color: $fond;
}

因此页面顶部和页面底部的溢出颜色会根据需要有所不同。

挂钩到滚动事件而不是调整大小事件

componentDidMount() {
    this.updateDimensions();
    window.addEventListener('scroll', this.updateDimensions);
}

componentWillUnmount() {
    window.removeEventListener('scroll', this.updateDimensions);
}

updateDimensions = () => {
    this.setState({heightSet: document.body.scrollHeight});
    console.log(document.body.scrollHeight);
}
import React, { useRef, useLayoutEffect, useState } from "react";

const Home = props => {
  const targetRef = useRef();
  const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
  const [initVal, setInitVal] = useState(0);
  const [height, setHeight] = useState({});

  useLayoutEffect(() => {
    if (targetRef.current) {
      setDimensions({
        width: targetRef.current.offsetWidth,
        height: targetRef.current.offsetHeight
      });
      setHeight({
        height: targetRef.current.offsetHeight + "px",
        border: "1px solid red"
      })
    }

  }, []);

  const hanleInput = (e) => {
    setInitVal(e.target.value);
  }

  const increaseHeight = () => {
    let totalHeight = Number(dimensions.height) + Number(initVal);
    setDimensions({
      width: targetRef.current.offsetWidth,
      height: totalHeight
    });
    setHeight({
      height: totalHeight + "px",
      border: "1px solid red"
    })
    setInitVal(0);
  }

  return (
    <div ref={targetRef} style={height} >
      <p>{dimensions.width}</p>
      <p>{dimensions.height}</p>
      <input type="number" value={initVal} onChange={hanleInput} />
      <button onClick={increaseHeight}>increaseHeight</button>
    </div>
  );
};

export default Home;