개인 프로젝트 - 2일 차

Rock Kyun·2023년 12월 22일
1
post-thumbnail

오늘 했던 것

  • 메인페이지 완성
  • 어제의 문제 해결

오늘의 결과물

어제 문제였던 것

  • Fontawesome 모듈을 동적으로 import 하는 것
    • FontAwesome은 동적 import가 불가능 했다..
      그래서 따로 공통 컴포넌트로 빼서 Icon을 담당하도록 하였다.

해결✅

<util/iconGenerator.js>

import * as icon from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";

// 아이콘 컴포넌트를 반환
export const retunIcon = (iconName, size = '1x', color = 'white') => {
  return <FontAwesomeIcon style={{ color }} icon={icon[iconName]} size={size} color="white" />;
};
	

오늘의 문제

  • 하나의 useRef여러 개의 값을 관리하는 것.

React에서 IntersectionObserver API 사용 과정

  • Intersection Observer를 사용할 때
    new IntersectionObserver()observe() 메서드는
    인자로 관찰 할 target을 전달해줘야 하는데
    target은 DOM Element다.
    그래서 리액트는 useRef를 사용하여 타겟을 전달해주는데
    방법은 아래와 같다.
  1. useRef Hook으로 변수 생성
  2. 관찰하고자 하는 요소에 ref속성을 주고
    그 요소를 useRef()를 할당한 변수의 current 값으로 할당한다.
  3. 컴포넌트 마운트 시 관찰 대상을 observe() 메서드에 등록한다.
const observeSection = () => {
    // observe() 메서드에 ref 속성을 가진 요소를 전달
    observer.observe(observeTarget.current)
  };
  1. IntersectionObserver의 callback 함수에
    관찰 대상이 나타났을 때(나타났을 때 외에도 여러가지 옵션이 있다)
    적용하고자 할 코드를 작성한다.
 // useRef를 하나 생성
 const observeTarget = useRef();

  // observe 할 대상이 화면에 나타나면 적용되는 코드
  const observer = new IntersectionObserver((e) => {
    e.forEach((el) => {
      if (el.isIntersecting) el.target.style.animationPlayState = "running";
    });
  });

  // 관찰 할 대상을 등록하는 함수
  const observeSection = () => {
    observer.observe(observeTarget.current)
  };

  // 컴포넌트가 mount 시 observer에 타겟을 전달한다
  useEffect(() => {
    observeSection();
  }, []);

 // UI
 <HireTextUl ref={observeTarget}>
   {listUI}
 </HireTextUl>

문제의 시작

  • 위와 같이 하다보니 문제가 생겼다
    애니메이션을 주고 싶은 대상이 많을 때
    useRef가 5-6개가 되어버린 것이다..

  • useRef를 하나만 사용할 때는
    자세한 작동원리를 모르고 사용했는데
    오늘 useRef의 생김새를 뜯어보게 됐다.

해결 과정

1. useRef 뜯어보기

  • useRef에 초기 값을 배열로 주게 되면 어떻게 되나 확인했다.
const test = useRef([]);
  console.log(test); // {current: Array(0)}

이렇게 되면 test.current 는 배열이란 거구나~ 하고 깨달았다.

2. ref.current 배열에 DOM 요소 추가하기

  • 아래의 코드를 보면 ref 속성 안에
    (el) => (observeTarget.current[1] = el) 요런 callback 함수가 있는데
    저 함수의 인자는 해당 DOM 요소를 뜻한다.
    따라서 callback 함수는 ref.current[1]에 해당 DOM 요소를 담겠다 라는 뜻인 것.
 <HireTextUl ref={(el) => (observeTarget.current[1] = el)}>
   {listUI}
 </HireTextUl>
 <ButtonBox ref={(el) => (observeTarget.current[2] = el)}></ButtonBox>
 // 생략

3. 이제 ref.current에 여러 DOM 요소를 담도록 하자

<HireTextUl ref={(el) => (observeTarget.current[1] = el)}>
   {listUI}
</HireTextUl>

<ButtonBox ref={(el) => (observeTarget.current[2] = el)}>
  	<Button
      width={160}
      height={60}
      isBackground={true}
      text={"Hire a trainer"}
	/>
	<Button width={160} height={60} text={"Talk in person"} />
</ButtonBox>

<ImageBox ref={(el) => (observeTarget.current[3] = el)}>
  <ImageEl src={"trainer"} />
</ImageBox>

4. 마지막으로 observe 메서드에 DOM 요소들을 등록해준다.

const observeElement = () => {
  observeTarget.current.forEach((el) => {
    observer.observe(el);
  });
};

느낀점

  • 늘 쓰던 속성(ref)이라도 저런 콜백함수를 사용할 수 있는지 몰랐다.
    저런 방식으로 ref의 current 값에 DOM 요소를 할당 할 수 있다니
    신세계다!

0개의 댓글