[TIL] 0324

yoon Y·2022년 3월 25일
0

2022 - TIL

목록 보기
61/109

TypeScript Project

리팩토링한 컴포넌트 구조로 기존 코드를 수정했다.

ImageSlide

최상위 부모인 ImageSliderPage의 상태로 현재 슬라이드 index와 슬라이드의 갯수를 저장해주었다.
슬라이드, 넘김 버튼, 포인터 3가지의 컴포넌트를 만들어 ImageSliderPage의 해당 태그에 각각 연결해주었다.


 setup() {
    this.state = {
      currentSlideIndex: 0,
      maxLength: imageUrlList.length,
    };
  }

 template() {
    return `
    <div id='Image-slider-container'>
      <div data-component="slider"></div>
      <div data-component="arrow-buttons"></div>
      <div data-component="dots"></div>
    </div>
    `;
  }
 
 mounted() {
    const $slider = this.$target.querySelector('[data-component="slider"]');
    const $dots = this.$target.querySelector('[data-component="dots"]');
    const $arrowButtons = this.$target.querySelector(
      '[data-component="arrow-buttons"]',
    );

    this.Slider = new Slider($slider, {
      currentSlideIndex: this.state.currentSlideIndex,
      imageUrlList,
    });

    this.Dots = new Dots($dots, {
      currentSlideIndex: this.state.currentSlideIndex,
      indexArr: Array.from({ length: this.state.maxLength }, (_, i) => i),
    });

    new ArrowButtons($arrowButtons, {
      onClickPrev: this.handleClickPrevButton.bind(this),
      onClickNext: this.handleClickNextButton.bind(this),
    });
  }

넘김 버튼 click handler함수를 ArrowButtons컴포넌트의 props으로 전달해서 이벤트를 걸어줬다.
콜백함수에는 currentSlideIndex를 변경시켜주는 로직이 작성되어있다.
0에서부터 슬라이드 최대갯수-1의 범위까지 순환하도록 구현했다.

  handleClickPrevButton() {
    const { currentSlideIndex, maxLength } = this.state;
    const newIndex =
      currentSlideIndex === 0 ? maxLength - 1 : currentSlideIndex - 1;

    this.setState({ ...this.state, currentSlideIndex: newIndex }, true);
  }

  handleClickNextButton() {
    const { currentSlideIndex, maxLength } = this.state;
    const newIndex =
      currentSlideIndex === maxLength - 1 ? 0 : currentSlideIndex + 1;

    this.setState({ ...this.state, currentSlideIndex: newIndex }, true);
  }

넘김 버튼을 클릭해 ImageSliderPage의 상태인 currentSlideIndex가 변경되면 Slider와 Dots컴포넌트가 바뀐 상태로 다시 렌더링되게 구현했다.
화면 상 변하지 않는 ArrowButtons는 리렌더링되지 않게 했다.

  reRender() {
    this.Slider.setState({
      ...this.Slider.state,
      currentSlideIndex: this.state.currentSlideIndex,
    });

    this.Dots.setState({
      ...this.Dots.state,
      currentSlideIndex: this.state.currentSlideIndex,
    });
  }

WaffleCard Refactoring

Intersection Observer도입

문제점
스크롤이 끝나면 useInterval을 중단 시키는 코드를 useInterval의 콜백함수 안에 작성해줬다.
문제점은 delay초마다 스크롤이 끝난지 확인하는 로직이 실행되어 비효율적이다.

 useInterval(
    () => {
      if (!(targetDom instanceof Element)) return;

      const { scrollLeft, clientWidth } = targetDom;
      const currentScrolledWidth = Math.ceil(scrollLeft + clientWidth);
      const isRenderedCards = currentScrolledWidth > targetDom.clientWidth;
      const isFinishScroll = currentScrolledWidth === targetDom.scrollWidth;
      isRenderedCards && isFinishScroll && setIsPlayMove(false); 
      targetDom.scrollLeft += 1;
    },
    15,
    isPlayMove,
  );

해결책
intersection observer를 도입하여, 마지막 카드를 감시 target으로 걸어준다.
마지막 카드가 전부 보여질 때 useInterval을 중단시키는 콜백함수를 실행시키는 방법이다.

callback ref

ref.current의 값이 바뀌어도 컴포넌트는 그 사실을 알지 못한다.
그렇기에 ref.current가 초기값에서 연결된 돔으로 바뀐 후 어떤 로직을 실행하게 하려면
useEffect를 사용해 의존성으로 ref.current를 걸어줘야했다.

하지만 callback ref를 사용하면 ref.current변경을 알아서 인지해, 돔 값이 할당 된 후 로직을 자동 실행시킬 수 있다.
돔의 ref속성에 함수를 할당해주면, 해당 함수의 파라미터로 dom이 들어오게되고
그것을 이용해 로직을 작성할 수 있다.
주의점은 ref에 할당하려는 함수는 꼭 useCallback으로 감싸서 리렌더링이 안되게 해야한다는 것.

참고 코드

import React, { useState, useCallback } from "react";
import Cat from "./components/Cat";
import "./styles.css";

export default function App() {
  const [height, setHeight] = useState(0);

  const callbackRef = useCallback((node) => {
    if (node !== null) {
      setHeight(node.getBoundingClientRect().height);
    }
  }, []);

  return (
    <div>
      <h4> 고양이가 세상을 구한다 ️</h4>
      <p> 내 키는 : {height}px 이야</p>
      <div ref={callbackRef}>
        <Cat />
      </div>
    </div>
  );
}

참고자료

intersectionobserver-support-horizontal-scrolling-observation
https://dev.to/itepifanio/horizontal-scroll-with-lazy-loading-578c
https://leehwarang.github.io/2020/11/29/ref.html

profile
#프론트엔드

0개의 댓글