react-waypoint icon indicating copy to clipboard operation
react-waypoint copied to clipboard

An example with two columns scrollable?

Open kud opened this issue 6 years ago • 17 comments

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

kud avatar Dec 05 '18 17:12 kud

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?

trotzig avatar Dec 06 '18 11:12 trotzig

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

kapture 2018-12-06 at 12 18 15

kud avatar Dec 06 '18 11:12 kud

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

kud avatar Dec 06 '18 11:12 kud

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

trotzig avatar Dec 06 '18 11:12 trotzig

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

What do you think I should check there?

kud avatar Dec 06 '18 17:12 kud

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

kud avatar Dec 06 '18 17:12 kud

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

trotzig avatar Dec 06 '18 17:12 trotzig

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 avatar Dec 06 '18 17:12 kud

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 avatar Dec 06 '18 17:12 kud

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 avatar Dec 06 '18 17:12 kud

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

kud avatar Dec 06 '18 18:12 kud

image

image

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

kud avatar Dec 06 '18 18:12 kud

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 avatar Dec 06 '18 18:12 kud

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

kud avatar Dec 06 '18 18:12 kud

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

trotzig avatar Dec 06 '18 20:12 trotzig

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

trotzig avatar Dec 06 '18 20:12 trotzig

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.

kud avatar Dec 06 '18 21:12 kud