Search code examples
javascriptreactjsdomscrolldrag

Access 'scrollLeft' property in react


I'm facing a problem with div property attributes when I convert my code from basic HTML and JS to react

the old code and the Desired result would be like this :

https://codepen.io/fadeomar/project/editor/DVWGjd

now when starting to convert this project to react it cant change the value of scrollLeft property

my question is how I can change the value of scrollLeft for a certain element in react, all I got when I searched this issue that setting event listener to the whole window object, not for a specific element in DOM

I thought to use reusable component for Drag and Scroll and here is the code

import React from 'react';
import PropTypes from 'prop-types';

export class ScrollDrag extends React.Component {
  constructor(props) {
    super(props);
    this.ref = React.createRef();
    this.state = {
      isScrolling: false,
      clientX: 0,
      scrollX: 0,
    };
  }

  onMouseDown = e => {
    this.setState({ ...this.state, isScrolling: true, 
     clientX: e.clientX });
  };

  onMouseUp = () => {
    this.setState({ ...this.state, isScrolling: false });
  };

  onMouseMove = e => {
    const { clientX, scrollX } = this.state;
    if (this.state.isScrolling) {
      this.ref.current.scrollLeft = scrollX + e.clientX - clientX;
      this.setState({scrollX: scrollX + e.clientX - clientX, clientX: e.clientX})
    }
  };

  render() {
    const { rootClass } = this.props;
    return (
      <div
        ref={this.ref}
        onMouseDown={this.onMouseDown}
        onMouseUp={this.onMouseUp}
        onMouseMove={this.onMouseMove}
        className={rootClass}
      >
        {React.Children.map(this.props.children, child =>
            React.Children.only(child))}
      </div>
    );
  }
}

ScrollDrag.defaultProps = {
  ref: { current: {} },
  rootClass: '',
};

ScrollDrag.propTypes = {
  ref: PropTypes.object,
  rootClass: PropTypes.string,
  children: PropTypes.string,
};

export default ScrollDrag;

then I use it as an heir order component in the app

this is my try : https://codesandbox.io/s/peaceful-butterfly-ndp6z?file

Any help to make this works be appreciated


Solution

  • Updated answer

    You were scrolling the wrong element. I removed the wrappers from the items and tweaked the css. I also had to reverse the polarity of the scrolling. Now it works.

    https://codesandbox.io/s/awesome-tree-s8miv?file=/src/DragScroll.js

    Original answer to original (now edited) question

    The error is caused by the fact that you're not using ref you've created in this component:

    render() {
        const { ref, rootClass } = this.props; // <-- this is wrong
        return (
          <div
            ref={ref}
            onMouseDown={this.onMouseDown}
            onMouseUp={this.onMouseUp}
            onMouseMove={this.onMouseMove}
            className={rootClass}
          >
            {React.Children.map(this.props.children, child =>
                React.Children.only(child))}
          </div>
        );
    

    It should just be like this:

    render() {
        const { rootClass } = this.props;
        return (
          <div
            ref={this.ref}
            onMouseDown={this.onMouseDown}
            onMouseUp={this.onMouseUp}
            onMouseMove={this.onMouseMove}
            className={rootClass}
          >
            {React.Children.map(this.props.children, child =>
                React.Children.only(child))}
          </div>
        );