[Next.js] 알파벳 클릭 시 스크롤 기능 구현

해달·2022년 7월 20일
0

알파벳 리스트를 만든 후에 알파벳 클릭 시 각 알파벳에 첫 아이템으로 스크롤을 위치시켜주어야했는데
그 과정에서 받은 조언과 피드백을 토대로 정리해보려고 한다.


스크롤 방식 정하기

초기에 생가했떤 방법은 서버에서 받아오는 데이터를 각 알파벳마다 개수를 세서
컴포넌트 높이 * 브랜드 수 = 스크롤 높이 로 지정해서 처리하려고 했다

{
 A : 2,
 B : 1,
  ,,,
}

이렇게 구현하려고 하니 문제점으로는
앞전에 브랜드 카운트 된 수는 어떤방식으로 처리할지 고민이 돼서 조언을 구해 다른 방법을 추려 보았다.

우선 offsetY 값을 정할 수 있는 방법을 3가지로 추렸다.

  1. 데이터리스트에서 첫번째 리스트인 애들만 찾아내어서 함수를 실행시킨다.
  2. 서버데이터 형식 변경 [['a' , 'a' , 'a'] , ['b','b','b']]
  3. 최소값 비교해서 저장

2번째 방법은 서버에서 데이터 형식을 변경해서 전달해주는 방법이였고
3번째 방법은 데이터를 저장하면서 offsetY의 값을 비교해서 각 알파벳 별로 최소값인 offsetY 를 저장하는 방법이였는데

첫번째 방법으로 리스트 중 처음으로 들어오는 알파벳의 값만 저장하도록 구현하기로 결정했다.


동작순서

실행되는 동작 순서로는 아래와 같이 정의했다.

  1. 페이지 렌더링 시 화면에 보여 줄 알파벳 리스트 만들기 (useEffect)
  2. 알파벳 리스트를 순회하면서 findIndex, startWith 를 이용하여 각 알파벳의 첫 index 값을 배열에 저장
  3. Lists 의 item별로 boolean 타입의 isFirst 값을 props로 전달
  4. isFirst 이 true일 경우에 object 형태로 offsetY 값 저장하기
  5. 클릭 시 scroll되도록 설정

알파벳 리스트 만들기

const getAlphabets = () => {
  const alphabetAsciiCodes = Array.from(Array(26), (e, i) => i + 65);
  const alphabets = alphabetAsciiCodes.map((x) => String.fromCharCode(x));

  return alphabets;
};
  1. Array에 내장되어있는 from 메서드를 이용해 26개의 빈 배열을 각 index값에 65를 더해
    각 알파벳의 아스키코드를 저장한다.
  2. fromCharCode 메서드로 아스키코드를 문자열로 변경해준다.

첫번째 알파벳 index 저장하기

const i = List?.findIndex(item => item.startsWith(a));

findIndex

주어진 판별 함수를 만족하는 배열의 첫 번째 요소에 대한 인덱스 를 반환합니다.
만족하는 요소가 없으면 -1을 반환합니다.

startsWith

어떤 문자열이 특정 문자로 시작하는지 확인하여 결과를 boolean 값으로 반환

첫번째 인덱스를 저장하기 위해 아이템의 첫번째 글자를 확인하여 boolean 값을 확인하고
findIndex는 전달받은 true인 값 중 첫번째 index를 찾는다.
찾은 index 값을 배열에 저장한다.


리스트 중 첫번째 아이템에서 offsetY 값 저장하기

리스트가 렌더링되면서 index 배열에서 includes 함수를 이용해
props로 isFirst 값을 전달 받는다.

getBoundingClientRect 메서드로 엘리먼트의 위치 값을 받아올 수 있다.

// offsetY 값 저장하기
const offsetY = ref?.current?.getBoundingClientRect().y;

아이템이 알파벳마다의 첫번째 아이템이고 offsetY의 값이 있다면
a: 460 과 같은 형태로 위치값을 저장한다.

  useEffect(() => {
    if (offsetY && isFirst) {
      onOffsetYSave(name[0], offsetY);
    }
  }, [isFirst, name, onOffsetYSave, offsetY]);

scrollTo 이용하여 스크롤 시키기

알파벳 클릭 시 존재하는 offsetY의 값이 있다면 scrollTo를 사용하여
지정된 위치로 스크롤 시켜주도록 처리하였다.

  const AlphabetClick = (alphabet: string) => {
      if (!offsets[alphabet]) return;
      scrollTo({
        top: offsets[alphabet],
        left: 0,
        behavior: 'smooth',
      });
    };

마치며,

초기에 알파벳 별로 Y의 값을 어떻게 저장할지에 대한 고민이 많아
팀원들에게 의견을 구했는데 여러가지의 방법을 알려주어서
다양하게 시도해보면서 적당한 방법을 찾은 거 같다.
스스로 찾아보려했다면 시간이 오래걸리거나 아예 알지 못했을 방법들이여서 의견내준 팀원들에게 감사하고 질문은 어렵지만 좋다는것..👀


reference

0개의 댓글