Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript offsetHeight not updating from initial rendered height?

I'm loading content into a div using the infinite scroll method but it's not working as it should be.

This is the calculation I'm using in my window.onscroll function to load new content :

window.innerHeight + document.documentElement.scrollTop ===
document.documentElement.offsetHeight

But document.documentElement.offsetHeight never receives an updated value when new content is added. It always stays at the initial value, which is causing the entire infinite scroll to work in reverse, only loading new content when you scroll to the top of the screen and not the bottom as expected.

I've made sure that the appended divs are being put in the right element, also tried using document.getElementById('wrapper').offsetHeight instead of pulling it off the body but I'm getting the same result.

I've also tried removing all relevant css styling just in case that was causing the issue, again, same result.

I know it's impossible for anybody to diagnose this in any detail without a lot more information, but it's a big project with many other elements that could potentially be causing this issue, so I'm just asking if anybody else has ever run up against something similar or has any suggestions of other things to try?

Many thanks!

** Here's a sandbox of a working version (where I got the code from originally). I just don't know why the offsetHeight element doesn't update in my codebase.

EDIT Added my React Component below, not sure that it will help diagnosis though.

import React, { Component, Fragment } from 'react';
import axios from 'axios';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

class ProfileFollowers extends Component {
  constructor(props) {
    super(props);
    this.state = {
      error: false,
      hasMore: true,
      isLoading: false,
      followers: []
    };
    
    window.onscroll = () => {
      const {
        loadFollowers,
        state: { error, isLoading, hasMore }
      } = this;

      if (error || isLoading || !hasMore) return;

      if (
        window.innerHeight + document.documentElement.scrollTop ===
        document.documentElement.offsetHeight
      ) {
        loadFollowers();
      }
    };
  }

  componentWillMount() {
    this.loadFollowers();
  }

  loadFollowers = () => {
    
      axios
        .get('https://randomuser.me/api/?results=10')
        .then(results => {
          
          const nextFollowers = results.data.results.map(follower => ({
            email: follower.email,
            name: Object.values(follower.name).join(' '),
            photo: follower.picture.medium,
            username: follower.login.username,
            uuid: follower.login.uuid
          }));

          this.setState({
            hasMore: this.state.followers.length < 100,
            isLoading: false,
            followers: [...this.state.followers, ...nextFollowers]
          });
        })
        .catch(err => {
          this.setState({
            error: err.message,
            isLoading: false
          });
        });
  };

  render() {
    const { error, hasMore, isLoading, followers } = this.state;

    return (
      <div id="profile-followers-wrap">
        {followers.map(follower => (
          <Fragment key={follower.username}>
            <hr />
            <div style={{ display: 'flex' }}>
              <img
                alt={follower.username}
                src={follower.photo}
                style={{
                  borderRadius: '50%',
                  height: 72,
                  marginRight: 20,
                  width: 72
                }}
              />
              <div>
                <h2 style={{ marginTop: 0 }}>@{follower.username}</h2>
                <p>Name: {follower.name}</p>
                <p>Email: {follower.email}</p>
              </div>
            </div>
          </Fragment>
        ))}
        <hr />
        {error && <div style={{ color: '#900' }}>{error}</div>}
        {isLoading && <div>Loading...</div>}
        {!hasMore && <div>No more!</div>}
      </div>
    );
  }
}

ProfileFollowers.propTypes = {
  auth: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth
});

export default connect(mapStateToProps)(ProfileFollowers);

EDIT 2 Added screenshot of console to show the problem in action.

enter image description here

like image 928
spice Avatar asked Mar 05 '23 23:03

spice


1 Answers

FFS! Found it... I had the height set to 100% on the global html element :

html {
  height: 100%; // Arrrrggghhhh!
  width: 100%;
}

This was preventing the offsetHeight from updating.

You won't believe how long it took to debug this so I'm leaving this here in case anybody else ever stumbles across a similar issue. Hope I can save somebody else a few hours of hair pulling :)

like image 186
spice Avatar answered Apr 05 '23 23:04

spice