티스토리 뷰

Web/React

[React] slide 구현하기

HOJJANG 2022. 9. 27. 16:36

1. setInterval

0.) 목표

현재 가리키고 있는 slide 의 index 를 currIndex 라고 한다.

이때 currIndex 를 2초마다 +1 시키고, 그에 따라 pagination 의 색이 변하게끔 만드려고 한다.

 

1.) 문제점

setInterval(() => {
    setCurrIndex((curr) => {
      curr++;
      if (curr > IMAGE_LENGTH) curr =1;
      return curr;
    })
}, 2000);

 

1-2-3-1-2-3 의 순서를 바랐는데... 예상과 달리 숫자가 이상하게 돈다.

찍혀나오는 숫자들 (일정하지 않다..)

2.) 문제 해결

state가 변함에 따라 setInterval도 함께 re-rendering이 되는 문제로,

useEffect()를 사용하여 해결했다.

 

컴포넌트가 마운트 됐을 때만 setInterval을 실행시켜줌에 따라,

컴포넌트가 리렌더링이 되어도 이전의 setInterval 현재의 함수에 영향을 미치지 않는다. 

  useEffect(() => {
    const timer = setInterval(() => {
      setCurrIndex((curr) => {
        curr++;
        if (curr > IMAGE_LENGTH) curr = 1;
        return curr;
      })
    }, 2000);
  }, [])

 

 

 

2. click으로 state 변경

0.) 목표

- click event로 navigation 을 가리키는 state를 변경하고자 한다.

 

1.) 문제점

- 클릭하면 2초간 기다린 뒤 다음 상태로 넘어가지 않고 클릭한 요소의 다음으로 바로 state가 넘어간다.

className={currIndex === 1 ? 'select' : ''}

리렌더링 문제인가? 하며 봤는데 click 이벤트가 발생하면 새로운 클래스가 지정되지조차 않는다.

state 변경은 잘 되는데 왜 안될까 싶어 코드를 다시 봤더니...

dataset에서 뽑는 index는 string 형식인데 엄격한 비교를 사용해서 클래스가 지정되지 않은 거였다... .

 

2.) 해결

일반 비교 구문으로 바꿔주거나

className={currIndex == 1 ? 'select' : ''}

dataset 값을 Number 형태로 바꿔준다.

const navOnClick = (e) => {
    const {index} = e.target.dataset;
    setCurrIndex((curr) => {
      curr = Number(index);
      return curr;
    })
}

 

 

3. state 에 따른 list 변화

0.) 목표

- 현 상태 : currIndex 변수(state)에 따라 pagination 이 변하는 상태

pagination (3->1로 넘어가기 전)

- 목표: state 가 변경될 때 마다 transfrom - translateX 속성으로 li를 왼쪽으로 이동시켜 슬라이드를 완성시킨다. 

? 다들 useRef 를 쓰라고 하는데 정확히 어떤 걸 하는 함수인지 잘 모르겠음...

 

1.) 문제

// * slide handler function
const slideHandler = (currIndex) => {
    const slideWidth = document.querySelector('.slide').clientWidth;
    const ul = document.querySelector('ul');
    switch(currIndex) {
      case 1:
        ul.setAttribute('style', `left: ${0}px`)
        break;
      case 2:
        ul.setAttribute('style', `left: ${-slideWidth}px`)
        break;
      case 3:
        ul.setAttribute('style', `left: ${-slideWidth * 2}px`)
        break;
      default:
        ul.setAttribute('style', `left: ${0}px`)
        break;
    }
}
useEffect(() => {
    const timer = setInterval(() => {
      setCurrIndex((curr) => {
        curr++;
        if (curr > IMAGE_LENGTH) curr = 1;
        // slideHandler(curr);
        return curr;
      })
      // * call slide handler
      slideHandler(currIndex);
      return () => clearInterval(timer);
    }, 4000);
}, [])

-  4초마다 슬라이드를 변경해주어야 하기 때문에 slideHandler() 함수를 4초마다 호출해 currIndex에 따라 left 속성으로 방향을 이동시키려고 했다.

- 하지만 예상과 달리 슬라이드는 첫번째에서 멈춰 있고, slideHandler()함수로 넘어오는 값도 계속 1로만 찍혔다.

 

 

2.) 해결

// * change pagination status 
useEffect(() => {
    const timer = setInterval(() => {
      setCurrIndex((curr) => {
        curr++;
        if (curr > IMAGE_LENGTH) curr = 1;
      // * call slide handler
        slideHandler(curr);
        return curr;
      })
      return () => clearInterval(timer);
    }, 4000);
}, [])

useEffect 내에서 setCurrIndex(setState함수)로 state가 변경된 이후 slideHandler를 실행시켜주었기 때문에 state의 변경이 적용되지 않았다.

 

따라서 setCurrIndex 함수 내에서 slideHandler를 호출하였다.

state 변경 - slideHandler - 다음 렌더링 전 의 로직으로 배치하면 slide처럼 동작한다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
글 보관함