0

can i access the isroll variable which is inside useEffect? I want to run scroll when the button is pressed. but in my case it doesn't work. i have tried by doing setState and it's working but i got a new problem on iscroll.on() which says "Cannot read properties of undefined" i don't know how to solve this problem. is there someone who can help me?

function Arrangement() {
  const ref = useRef(null);

  const [prevButton, setPrevButton] = useState(false);
  const [nextButton, setNextButton] = useState(true);

  useEffect(() => {
    const iscroll = new IScroll(ref.current, { // how to export this variable?
      keyBindings: true,
      scrollX: true,
      mouseWheel: true,
      click: true
    });

    iscroll.on("scrollEnd", () => {
      if (iscroll.x === 0) {
        setPrevButton(false);
      } else {
        setPrevButton(true);
      }

      if (iscroll.x === iscroll.maxScrollX) {
        setNextButton(false);
      } else  {
        setNextButton(true);
      }
    });

    return () => {
      iscroll.destroy();
    }
  }, []);

  const onPrevButtonHandler = () => {
    iscroll.scrollBy(220, 0, 600); // not working
  }

  const onNextButtonHandler = () => {
    iscroll.scrollBy(-220, 0, 600); // not working
  }

  return (
    <div className={classes.Container}>
      <button className={clsx(classes.Button, classes.ButtonLeft, {
        [classes.Button__active]: prevButton
      })} onClick={onPrevButtonHandler} type="button" aria-label="Prev button">
        <ChevronLeft />
      </button>
      <div className={classes.Wrapper} ref={ref}>
        <ul>
          <li></li>
        </ul>
      </div>
      <button className={clsx(classes.Button, classes.ButtonRight, {
        [classes.Button__active]: nextButton
      })} onClick={onNextButtonHandler} type="button" aria-label="Next button">
        <ChevronRight />
      </button>
    </div>
  );
}

export default Arrangement;

I am open to any suggestions given.

skyboyer
  • 22,209
  • 7
  • 57
  • 64
  • Can you post the version where you turned `iScroll` into a state variable? –  Sep 18 '21 at 10:01
  • i use "iscroll": "^5.2.0", – Emil Jamel Mahmuda Sep 18 '21 at 10:04
  • I meant, post the code you tried where `iScroll` is part of the state, as opposed to a local variable. –  Sep 18 '21 at 10:06
  • the difference is that I replaced the iscroll variable with setIScroll(new IScroll(ref.current, { .... })) – Emil Jamel Mahmuda Sep 18 '21 at 10:21
  • Yeah, and next you called `iScroll.on()` and got the error. That won't work, because in React, [state updates are async](https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous). You need `const theScroll = new IScroll(...);`, and now you can call `theScroll.on(...)` and `setIScroll(theScroll);` in any order you like. –  Sep 18 '21 at 10:25
  • can you give me a sample code please? sorry i'm new in using react – Emil Jamel Mahmuda Sep 18 '21 at 10:27
  • We seem to have a communication problem. I just gave you the code you need, right there in my comment. –  Sep 18 '21 at 10:28

1 Answers1

0

Move your iscroll variable into a reference or a state.

Therefore, init it from the ref callback itself:

function Arrangement() {
  const iscroll = useRef();
  // OR
  const [iscroll, setIscroll] = useState();

  return (
    <div className={classes.Container}>
      ...
      <div
        ref={(node) => {
          const iscrollInstance = new IScroll(node, {
            keyBindings: true,
            scrollX: true,
            mouseWheel: true,
            click: true,
          });
          iscroll.current = iscrollInstance;
          // OR
          setIscroll(iscrollInstance);
        }}
      >
        ...
      </div>
      ...
    </div>
  );
}

Notice the usage of iscroll depending on ref/state:

iscroll.current.on("...") // if its a ref
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • Turns out this is a [dupe](https://stackoverflow.com/questions/30782948/why-calling-react-setstate-method-doesnt-mutate-the-state-immediately) –  Sep 18 '21 at 10:26