0308 받아온 데이터 정렬하기

냐하호후·2022년 3월 8일
0

데이터 정렬하기

받아온 데이터 형식

const data = [
  {
    id: 145521,
    point: 4,
    contents:
      '너무 특이한 골지 니트에요.\n시크하게 입기에 딱 좋고, 스키니와 와이드 팬츠 둘 다 너무 잘어울려서 애용하고 있습니다!',
    img: ['44cbea94e62dc80fbc4ecfed4b73e29a.jpeg'],
    like: 66,
    regdt: '2022-02-22 04:28:59',
    thumbnail: '44cbea94e62dc80fbc4ecfed4b73e29a-t.jpeg',
    reply: 3,
    nickname: 'errorr',
  },
  //생략
  ]

최신순 정렬

처음엔 데이터가 최신순으로 이미 정렬이 되어있어서 그냥 받아온 데이터를 보여줬었다.
하지만 리뷰를 새로 작성하면 새로운 리뷰가 배열의 맨 끝에와서 최신순 정렬 로직을 만들었다.

   let arr = data.slice();
      let orderedDate = arr.sort(
        (a, b) => new Date(b.regdt) - new Date(a.regdt),
      );
      setList(orderedDate);

댓글 많은 순 정렬

 let slice = data.slice();
      slice.sort((a, b) => {
        //comment가 없으면 value가 undefined
        let aLength = 0;
        let bLength = 0;
        if (a.comment) aLength = a.comment.length;
        if (b.comment) bLength = b.comment.length;
        return bLength - aLength;
      });

댓글은 객체요소로 이루어진 배열이다.
sort메서드를 이용해서 댓글이 많은 순서대로 정렬되도록 만들었다.

랜덤 정렬

      let slice2 = data.slice();
      slice2.sort(() => Math.random() - 0.5);
      setList(slice2);

Math.random()을 사용하면 0 이상 1 미만의 부동소숫점 의사 난수가 나온다.
Math.random() - 0.5는 음수 양수를 무작위로 반환하고, 그 값에 따라 sort함수에 의해 순서가 뒤섞인다.

클로저

사실 처음엔 버튼을 누르면 상태가 바뀌도록 아래의 코드로 작성했다. 그랬더니 정렬은 잘 되었지만 맞는 타이밍에 변하지 않았다. 2번 눌러야 정렬이 생각대로 되었다.

  const handleChangeFilter = f => {
    setFilter(f);
 if (filter === 'latest') {
      let arr = data.slice();
      let orderedDate = arr.sort(
        (a, b) => new Date(b.regdt) - new Date(a.regdt),
      );
      setList(orderedDate);
    } else if (filter === 'review') {
      let slice = data.slice();
      slice.sort((a, b) => {
        let aLength = 0;
        let bLength = 0;
        if (a.comment) aLength = a.comment.length;
        if (b.comment) bLength = b.comment.length;
        return bLength - aLength;
      });
      setList(slice);
    } else if (filter === "random") {
      let slice2 = data.slice();
      slice2.sort(() => Math.random() - 0.5);
      setList(slice2);
    }
  };

다행히도 useEffect안으로 handleChangeFilter 코드를 옮겨 넣으니 한번에 상태가 잘 변했다. 한번에 바로 변하지 않았던 원인은 클로저 때문이었다.

클로저를 기반으로 함수가 상태 값을 사용하고, 상태의 업데이트는 기존 클로저의 영향을받지 않고 새로운 클로저가 생성되는 다음 다시 렌더링에 반영된다. 현재 상태 값은 기존 클로저에 의해 얻어지며 다시 렌더링이 발생하면 클로저는 함수가 다시 생성되는지 여부에 따라 업데이트된다.

불변성을 지키자

Uncaught TypeError: Cannot assign to read only propery '0' of obejct '[object Array]'

그리고 배열도 처음엔 slice해서 사용하지않고 바로 data를 가공하려고 했었다. 에러가 발생했었다.
React는 불변성을 지켜주어야만 리액트 컴포넌트에서 상태가 업데이트됐음을 감지할 수 있고 이에 따라 필요한 리렌더링이 진행된다.
기존 상태를 직접 수정하게 되면, 값을 바꿔도 리렌더링이 되지 않는다.

배열 또한 불변성의 법칙을 어기면 안되기 때문에 복사를해서 새로운 배열을 만들어 변경시켜주었다. slice외에도 concat이나 spread 연산자를 사용하면 된다.

그 외

map돌릴때 key에 index값을 넣으면 안된다. index를 사용했다면 항목의 순서가 바뀌었을 경우 key 또한 바뀌었을 거고 이는 state를 엉망으로 만들거나 원하지 않는 방식으로 컴포넌트를 바꿀 수 있다.

참고

렌더링 바로 안됌(useEffect)

profile
DONE is better than PERFECT

0개의 댓글