0

I was trying to create a list of movies like in Netflix, in which left arrow appears when i slide it to the right. And left arrow disappears when list gets back to original position.

Why is the value of slideNumber remaining same even after i update it using setSlideNumber?

Image of the lists i am trying to make

function List() {
    const [slideNumber, setSlideNumber] = useState(0);    //USE STATE HOOK
    const [isMoved, setIsMoved] = useState(false);

    const listRef = useRef();

    const handleClick = (direction) => {
        setIsMoved(true);
        let distance = listRef.current.getBoundingClientRect().x -50;
        if(direction === "right" && slideNumber<5){
            setSlideNumber(slideNumber+1);
            listRef.current.style.transform = `translateX(${distance - 230}px)`
        }
        if(direction === "left" && slideNumber>0){
            console.log(slideNumber);          //THIS LINE
            setSlideNumber(slideNumber-1);  
            console.log(slideNumber);           //AND THIS LINE GIVES SAME OUTPUT
            if(slideNumber===1){
                setIsMoved(false);
            }

            listRef.current.style.transform = `translateX(${distance + 230}px)`
        }
    }

    return (
        <div className='list'>
            <span className="listTitle">Continue Watching</span>
            <div className="wrapper">
                <ArrowBackIosOutlinedIcon
                className='sliderArrow left'
                onClick = {()=>handleClick("left")} 
                style={{display: !isMoved && "none"}}
                />
                <div className="container" ref={listRef}>
                    <ListItem />
                    <ListItem />
                    <ListItem />
                    <ListItem />
                    <ListItem />
                    <ListItem />
                    <ListItem />
                    <ListItem />
                    <ListItem />
                    <ListItem />
                </div>
                <ArrowForwardIosOutlinedIcon className='sliderArrow right' onClick = {()=>handleClick("right")}/>
            </div>
        </div>
    );
}

1 Answers1

1

React will batch all your state change and will update the state only once to avoid any unnecessary render. As such, you will get an updated state only during the next render, not in the same stack you are currently executing.

In your case it will wait for your handleClick function to finish its execution before updating the state, hence the second console.log with the same output.

For your following condition to work you should use an intermediary variable:

if(direction === "left" && slideNumber > 0){
  const newSlideNuber = slideNumber - 1
  setSlideNumber(newSlideNumber);  

  if(newSlideNumber === 1){
    setIsMoved(false);
  }

  listRef.current.style.transform = `translateX(${distance + 230}px)`
}

You can find more information about the batching behaviour in React in this github discussion

P.E. Joëssel
  • 1,393
  • 10
  • 18