civiccc/react-waypoint

An example with two columns scrollable?

kud opened this issue · 17 comments

kud commented

Do you think it could be possible to make an example with two columns scrollable?

This is my try but I don't get it

  • index.js
import styles from "./index.module.css"

import React from "react"
import PropTypes from "prop-types"
import Waypoint from "react-waypoint"
import randomColor from "randomcolor"

function getRandomInt(min, max) {
  min = Math.ceil(min)
  max = Math.floor(max)

  return Math.floor(Math.random() * (max - min)) + min
}

class Block extends React.Component {
  render() {
    return (
      <div id={this.props.id} ref={this.props.innerRef} style={{
        height: getRandomInt(200, 1200) + "px",
        backgroundColor: randomColor({ seed: this.props.i*10 }),
        fontWeight: "bold",
        fontSize: "20px",
        color: "white",
        padding: "20px",
        textShadow: "0px 0px 1px black",
        borderBottom: "4px dashed white",
        display: "block",
      }}>
        {this.props.id}
      </div>
    )
  }
}

Block.propTypes = {
  innerRef: PropTypes.func.isRequired,
  id: PropTypes.string.isRequired,
  i: PropTypes.any.isRequired,
}

const BlockWithRef = React.forwardRef((props, ref) => {
  return <Block innerRef={ref} {...props} />
})

class SandboxPage extends React.Component {
  handleEnterA = (el, props) => {
    console.log("A: ENTER", el)
  }

  handleLeaveA = (el, props) => {
    console.log("A: LEAVE", el)
  }

  handleEnterB = (el, props) => {
    console.log("B: ENTER", el)
  }

  handleLeaveB = (el, props) => {
    console.log("B: LEAVE", el)
  }

  render() {
    return (
      <div className={styles.main} id="main">
        <div className={styles.column} id="A">
          {Array.from({length: 31}, (_, el) => (
            <Waypoint
              key={`A-${el}`}
              onEnter={(props) => { this.handleEnterA(el, props) }}
              onLeave={(props) => { this.handleLeaveA(el, props) }}
              fireOnRapidScroll
              topOffset="100px"
            >
              <BlockWithRef id={`A-${el}`} i={el} />
            </Waypoint>
          ))}
        </div>

        <div className={styles.column} id="B">
          {Array.from({length: 31}, (_, el) => (
            <Waypoint
                key={`B-${el}`}
                onEnter={(props) => { this.handleEnterB(el, props) }}
                onLeave={(props) => { this.handleLeaveB(el, props) }}
                fireOnRapidScroll
            >
              <BlockWithRef id={`B-${el}`} i={el} />
            </Waypoint>
          ))}
        </div>
      </div>
    )
  }
}

export default SandboxPage
  • index.module.css
.main {
  display: grid;
  grid-template-columns: repeat(2, 1fr)
}

.column {
  overflow-y: scroll;
  height: 100vh;
}

Thank you

Can you describe more specifically what's not working? Is it that the waypoints aren't firing at all? Or perhaps firing at the wrong time?

kud commented

I'd like to trigger enter and leave on each column, but nothing happens now.

kapture 2018-12-06 at 12 18 15

kud commented

Each block should trigger "enter" and "leave" but nothing happens and I've tried to change the scrollableAncestor, it didn't fix it.

If you add the debug prop to the waypoints, the console log might contain some information that can help you resolve this.

kud commented

I already did it but to be honest, no :(

What do you think I should check there?

kud commented

By any chance, is there a conflict with css grid or flexbox?

This shouldn't be because of flexbox or css grid. In the debug output, I would check that the scrollable ancestor is set to the right elements (the .column divs).

kud commented

My trouble is here and I don't know why yet:

.column {
/*   overflow-y: auto; */
/*   height: 100vh; */
}

as seen, disabled works. But I don't have my both scrolls, i've got a global scroll on the page.

kud commented

Yeah I wanted to check the scrollableAncestor, the problem is I only see that in the debug:

image

and I don't get it. It makes me think it's "window" there and no .column but I'm not sure at all.

Sorry for the live debug. (that's why I wanted to create a chat, haha)

kud commented

OH MY GOD. I understand now why you think the debug mode could help me.

On Chrome (canary) I don't have the same result, which there helps me, yes:

image

We've got a "bug" with Firefox (Nightly); either it's firefox which displays not enough, or it's the way you display the debug.

kud commented

Oh god, it's worst. It's not about debugging, it's about how the scrollableAncestor is detected on chrome and firefox.

kud commented

image

image

I don't get the same result on firefox and chrome, the element is "visible", not "auto".

kud commented

For a reason I don't explain yet, firefox has some troubles there:

function () {
      function _findScrollableAncestor() {
        var _props = this.props,
            horizontal = _props.horizontal,
            scrollableAncestor = _props.scrollableAncestor;


        if (scrollableAncestor) {
          return resolveScrollableAncestorProp(scrollableAncestor);
        }

        var node = this._ref;

        while (node.parentNode) {
          node = node.parentNode;

          if (node === document.body) {
            // We've reached all the way to the root node.
            return window;
          }

          var style = window.getComputedStyle(node);
          var overflowDirec = horizontal ? style.getPropertyValue('overflow-x') : style.getPropertyValue('overflow-y');
          var overflow = overflowDirec || style.getPropertyValue('overflow');

          // right here, firefox thinks it's "visible" on the first instance of the loop, where chrome says "auto"

          if (overflow === 'auto' || overflow === 'scroll') {
            return node;
          }
        }

        // A scrollable ancestor element was not found, which means that we need to
        // do stuff on window.
        return window;
      }

      return _findScrollableAncestor;
    }()
kud commented

And the weirdest thing is it works well there: https://jsfiddle.net/_kud/u76b40Lr/5/

I wonder if the styles are applied asynchronously some way? Do things change if you inject styles earlier somehow?

By the way, thanks for being so persistent here. I appreciate you trying to pin this down!

kud commented

Thank you @trotzig your component is amazing, I use it all the time. However, here I have to understand why it doesn't work like I'd to.

My goal here is to have two synchronised scrolls depending on where you are on ONE scroll.

But to be fair I think this discussion should be in a chat. :)

And about your note, the weird thing is that I've got hot reload, and when hot reload runs (like when I save my file), my render runs once again and seems to make it work. So I really wonder if I don't have a problem with the lifecycle on React but it's still weird it only happens on Firefox for the moment.