2024.03.01 TIL

Oneik·2024년 3월 1일
0
post-thumbnail

단방향 데이터 흐름

React는 단방향 데이터 흐름에 따라, 상태(state)와 같은 데이터가 항상 상위 컴포넌트에서 하위 컴포넌트로 흐른다.

그렇다면, 하위 컴포넌트에서 상위 컴포넌트의 상태(state)를 변경할 수 있는 방법은 없을까?

여기서 사용할 수 있는 방법이 상태 끌어올리기(Lifting State Up)다.

상태 끌어올리기

상태 끌어올리기(Lifting State Up)는 하위 컴포넌트에서 상위 컴포넌트의 상태를 변경하는 것을 말한다. 상위 컴포넌트의 상태를 변경하는 함수하위 컴포넌트로 전달하고, 이 함수를 하위 컴포넌트에서 실행하게 되면 상위 컴포넌트의 상태를 변경할 수 있다.

사용 방법

// Cart.tsx
function Cart() {
    const { carts, deleteCartItem, isEmpty } = useCart();
    const [checkedItems, setChekedItems] = useState<number[]>([]);
  
    const handleCheckItem = (id: number) => {
        if (checkedItems.includes(id)) {
            // 언체크
            setChekedItems(checkedItems.filter((item) => item !== id));
        } else {
            // 체크
            setChekedItems([...checkedItems, id]);
        }
    };
  	return (
    	<>
        	<div className="content">
              {carts.map((item) => (
                <CartItem
                  key={item.id}
                  cart={item}
                  checkedItems={checkedItems}
                  onCheck={handleItemDelete}
                />
              ))}
        	</div>
        	...
        </>
    );
}
  • 장바구니에서 체크한 도서의 id만을 가지고 있는 checkedItems 상태, 그리고 상태를 수정하는 handleCheckItem 함수 객체를 onCheck에 담아CartItem 이라는 하위 컴포넌트로 전달하였다.
// CartItem.tsx
interface Props {
  cart: Cart;
  checkedItems: number[];
  onCheck: (id: number) => void;
}

function CartItem({cart, checedItem, onCheck }: Props) {
  const isChecked = useMemo(() => {
    return checkedItems.includes(cart.id);
  }, [checkedItems, cart.id]);
  
  const handleCheck = () => {
    onCheck(cart.id);
  };
  
  return (
    <div className='check'>
      <div>
        <CheckIconButton
          isChecked={isChecked}
          onCheck={handleCheck}
        />
      </div>
    </div>
    ...
  );
}
  • 상위 컴포넌트로부터 전달받은 상태에 cart.id가 존재하는지 존재하지 않는지 반복해야하기 때문에, useMemo를 사용해 이전 값을 기록하도록 하고, checkedItemscart.id가 변경되면 다시 계산하도록 설정한다.
  • 상위 컴포넌트로부터 전달받은 상태를 변경하는 함수인 onCheckcart.id를 인자로 넣고, 하위 컴포넌트인 CheckIconButton에 Props로 전달한다.
// CheckIconButton.tsx
interface Props {
    isChecked: boolean;
    onCheck: () => void;
}

function CheckIconButton({ isChecked, onCheck }: Props) {
    return (
        <CheckIconButtonStyle onClick={onCheck}>
            {isChecked ? <FaRegCheckCircle /> : <FaRegCircle />}
        </CheckIconButtonStyle>
    );
}
  • useMemo에 저장된 값이 false라면, 체크를 할 수 있는 원 이미지를 보여주고, true 값이라면, 체크된 원을 보여준다.
  • 이미지 클릭이라는 이벤트가 발생하면, Props로 전달받은onCheck 함수를 호출하여, checkedItems의 상태에 cart.id가 존재한다면, 상태를 변경한다.

위와 같은 방식으로 하위 컴포넌트에서 상위 컴포넌트의 상태를 변경할 수 있다. 즉, 상위 컴포넌트에서 전달받은 상태 변경 함수를 하위 컴포넌트의 특정한 이벤트가 발생했을 때, 호출하여 상태를 변경할 수 있다.

profile
초보 개발자의 블로그입니다

0개의 댓글

관련 채용 정보