[React] part2. 비동기로 state를 변경할 때 주의점!!

지렁·2023년 11월 23일
0
post-custom-banner

이전 포스팅대로 pagnation을 구현하였다

하지만

Network 탭에서 No throtting -> Slow 3g 로 버그 테스트를 해보면

더보기 버튼 누른 후 삭제 버튼을 누르면
사라졌다가 데이터 로딩이 완료되면 다시 생기는 현상이 발생한다

원인은 삭제한 item state 값이 변경이 안된 item state가 렌더링되기 때문

흐름

-더보기 버튼 클릭하면 삭제버튼 클릭 전 item가 렌더링

  • handleLoad 함수에서 getReview 비동기 함수를 호출
  • 호출하는동안 삭제버튼 클릭
  • handleDelete 함수에서 items state 값을 변경해서 해당 요소 삭제된 채로 렌더링
  • getReview 비동기 함수에 response가 도착한 후 items를 변경하려고하는데 이때의 handleLoad 내의 items 는 삭제되기 전 items다
function App() {
  const [items, setItems] = useState([]);
  //평점 높은 순으로 정렬하기
  const [order, setOrder] = useState("createdAt");
  const [offset, setOffset] = useState(0);
  const [hasNext, setHasNext] = useState(true);

  const sortedItems = items.sort((a, b) => b[order] - a[order]); // 동적인 속성 접근

  const handleDelete = (id) => {
    const newItmes = items.filter((i) => i.id !== id);
    setItems(newItmes);
  };

  const handleLoad = async (option) => {
    const { reviews, paging } = await getReviews(option);
    if (option.offset === 0) {
      setItems(reviews);
    } else {
      setItems([...items, ...reviews]);
    }
    setOffset(option.offset + reviews.length);
    setHasNext(paging.hasNext);
  };

  useEffect(() => {
    handleLoad({ order, offset, limit: 6 });
  }, [order]);

  return (
    <>
      <button onClick={() => setOrder("createdAt")}>최신순</button>
      <button onClick={() => setOrder("rating")}>평점순</button>
      <ReviewList items={sortedItems} onDelete={handleDelete}></ReviewList>
      {hasNext && (
        <button onClick={() => handleLoad({ order, offset, limit: 6 })}>
          더보기
        </button>
      )}
    </>
  );
}

settter 함수에 콜백함수를 전달하여 해결 가능

const handleLoad = async (option) => {
    const { reviews, paging } = await getReviews(option);
    if (option.offset === 0) {
      setItems(reviews);
    } else {
      setItems((prevItems)=>[...prevItems, ...reviews]);
    }
    setOffset(option.offset + reviews.length);
    setHasNext(paging.hasNext);
  };

전달되는 파라미터는 바로 이전 state 값이다
=> 리액트가 현재시점의 state 값을 전달해준다

profile
공부 기록 공간 🎈💻
post-custom-banner

0개의 댓글