React: state 끌어올리기(Lifting State Up)

나는야 토마토·2022년 3월 5일
0

React

목록 보기
6/9
post-thumbnail
post-custom-banner

상태 끌어올리기

단방향 데이터 흐름이라는 원칙에 따라, 하위 컴포넌트는 상위 컴포넌트로부터 전달받은 데이터의 형태 혹은 타입이 무엇인지만 알 수 있다. 데이터가 state로부터 왔는지, 하드코딩으로 입력한 내용인지는 알지 못한다.

그러므로 하위컴포넌트에서의 어떤 이벤트로 인해 상위 컴포넌트의 상태가 바뀌는 것은 마치 "역방향 데이터 흐름"과 같이 조금 이상하게 들릴 수 있다...! React가 제시하는 해결책은 다음과 같다..!

상위 컴포넌트의 "상태를 변경하는 함수" 그 자체를 하위 컴포넌트로 전달하고, 이 함수를 하위 컴포넌트가 실행한다.

이것이 바로 "상태끌어올리기"이다!! 단방향 데이터 흐름의 원칙에 부합하는 해결방법이다.

그러면 상태끌어올리기를 하기 위해서는 어떻게 해야할까라는 의문이 들 것이다...! 바로 js의 callback을 이용하면 된다!

Callback 다시보기

콜백(callback)은 다른 함수(고차함수)의 인자로 전달되는 함수를 의미한다.
다시 설명하자면 callback은 비동기 프로그램때문에 나온 함수라고 생각하면 된다. 컴퓨터는 한 번에 한가지 일만 처리한다. 그러니깐 작업을 요청한 이후에 다음 작업을 진행할 수 없다. 만약 통신 과정이 포함되어있고, 데이터를 보낸 이후에 답이 없다면 멈춰버리기 때문에 이러한 점을 해결하고자 비동기 프로그램을 위해서 나온 함수가 콜백함수이다. 즉, 콜백함수는 비동기 이벤트가 실행되고 난 이후에 실행될 함수를 의미한다.

// 고차함수
function each(array, iterator) {
  for(let i = 0; i < array.length; i++) {
    let element = array[i]
    iterator(element, i, array)
  }
}

// 콜백 함수
function printElement(element) {
  console.log(element)
}

each(['hello', 'world'], printElement);

이제 React의 해결책에서 알아보자!
React에선 다음과 같이 말했다.

상위 컴포넌트의 "상태를 변경하는 함수" 그자체를 하위 컴포넌트로 전달하고, 이 함수를 하위컴포넌트가 실행한다.

여기서 말하는 상태를 변경하는 함수는 바로 handleChangeValue이다. 전달은 props를 이용하면 된다!

function ParentComponent() {
  const [value, setValue] = useState("날 바꿔줘!");

  const handleChangeValue = () => {
    setValue("보여줄게 완전히 달라진 값");
  };

  return (
    <div>
      <div>값은 {value} 입니다</div>
      <ChildComponent handleButtonClick={handleChangeValue}  />
    </div>
  );
}

childComponent는 마치 고차함수가 인자로 받은 함수를 실행하듯, props로 전달받은 함수를 컴포넌트 내에서 실행할 수 있게 된다. "상태 변경 함수"는 버튼이 클릭할 때 실행되기를 원하기 때문에 해당 부분에 콜백함수를 실행시켜주면 된다...!

function ChildComponent({ handleButtonClick }) {
  const handleClick = () => {
    // Q. 이 버튼을 눌러서 부모의 상태를 바꿀 순 없을까?
    // A. 인자로 받은 상태 변경 함수를 실행하자!

    handleButtonClick()
  }

  return (
    <button onClick={handleClick}>값 변경</button>
  )
}

또한 필요에 따라 설정할 값을 콜백 함수의 인자로 넘길 수도 있다!

function ParentComponent() {
  const [value, setValue] = useState("날 바꿔줘!");

  const handleChangeValue = (newValue) => {
    setValue(newValue);
  };

  // ...생략...
}

function ChildComponent({ handleButtonClick }) {
  const handleClick = () => {
    handleButtonClick('넘겨줄게 자식이 원하는 값')
  }

  return (
    <button onClick={handleClick}>값 변경</button>
  )
}

이 보다 실용적인 예제를 원하신다면 공식 문서에서 찾을 수 있습니다!

profile
토마토마토
post-custom-banner

0개의 댓글