하위 컴포넌트(NewTweetForm)에서의 클릭 이벤트가, 부모의 상태를 바꾸어야만 하는 상황이 왔습니다. 이를 어떻게 해결할 수 있을까요?
이를 해결할 수 있는 키워드는 바로 "State 끌어올리기(Lifting state up)"입니다.
결론부터 말하자면, 이는 상태를 변경시키는 함수(handler)를 하위 컴포넌트에 props로 전달해서 해결할 수 있습니다. 이는 마치 콜백 함수를 사용하는 방법과 비슷합니다.
그럼 다음 강의에서 본격적으로 상태 끌어올리기를 배워봅시다
단방향 데이터 흐름이라는 원칙에 따라, 하위 컴포넌트는 상위 컴포넌트로부터 전달받은 데이터의 형태 혹은 타입이 무엇인지만 알 수 있습니다. 데이터가 state로부터 왔는지, 하드코딩으로 입력한 내용인지는 알지 못합니다.
DOM을 사용해서도 할 수 있지만, React에서 단방향 데이터 흐름으로 만들 때 우리가 원하는 기능을 더 자동화하여 만들 수 있다. 그렇게 하기 위해서는 컴포넌트들은 독립적으로 역할에 충실해야 한다.
그러므로 하위 컴포넌트에서의 어떤 이벤트로 인해 상위 컴포넌트의 상태가 바뀌는 것은 마치 "역방향 데이터 흐름"과 같이 조금 이상하게 들릴 수 있습니다. React가 제시하는 해결책은 다음과 같습니다.
상위 컴포넌트의 "상태를 변경하는 함수" 그 자체를 하위 컴포넌트로 전달하고, 이 함수를 하위 컴포넌트가 실행한다
여전히 단방향 데이터 흐름의 원칙에 부합하는 해결 방법입니다. 바로 이것이 "상태 끌어올리기"
입니다.
React는 기본적으로 단방향 데이터 흐름이라는 원칙을 가집니다. 상위 컴포넌트에서 하위로는 이동할 수 있지만 반대로는 불가합니다. 그러나 종종 동일한 데이터에 대한 변경사항을 여러 컴포넌트에 반영할 필요가 생깁니다. 이 때, state 끌어올리기 개념으로 데이터 변경사항을 상위 컴포넌트로 전달할 수 있습니다. 데이터를 직접 상위로 전달하는 것과는 다르게, state를 직접 전달하는 것이 아닌 state 갱신 함수를 전달 받아 해당 함수를 실행시키는 원리입니다.
함수 내에서 어떤 구현이 함수 외부에 영향을 끼치는 경우 해당 함수는 Side Effect가 있다고 이야기합니다. React에서는 컴포넌트 내에서 fetch를 사용해 API 정보를 가져오거나 이벤트를 활용해 DOM 직접 조작할 때 Side Effect가 발생했다고 말합니다.
순수 함수란, 오직 함수의 입력만이 함수의 결과에 영향을 주는 함수를 의미합니다. 함수의 입력이 아닌 다른 값이 함수의 결과에 영향을 미치는 경우, 순수 함수라고 부를 수 없습니다. 또한 순수 함수는, 입력으로 전달된 값을 수정하지 않습니다.
리액트 개발자분들이 우리가 리액트를 사용할 때 순수 함수를 강제하기 위해서 리액트를 단방향 데이터 흐름으로 만들었다. 하지만 가끔 하위 컴포넌트에서 상위 컴포넌트의 state를 조작해야 할 때가 있다. 이때 사용하는 게 상태 끌-올 이다.
우리가 앞서 배운 React의 함수 컴포넌트는, props가 입력으로, JSX Element가 출력으로 나갑니다. 여기에는 그 어떤 Side Effect도 없으며, 순수 함수로 작동합니다.
useEffect
는 컴포넌트 내에서 Side effect를 실행할 수 있게 하는 Hook 입니다.
useEffect
의 첫 번째 인자는 함수입니다. 해당 함수 내에서 side effect를 실행하면 됩니다. 이 함수는 다음과 같은 조건에서 실행됩니다.
최상위에서만 Hook을 호출합니다.
React 함수 내에서 Hook을 호출합니다.
useEffect
의 두 번째 인자는 배열입니다. 이 배열은 조건을 담고 있습니다. 여기서 조건은 boolean 형태의 표현식이 아닌, 어떤 값의 변경이 일어날 때를 의미합니다. 따라서, 해당 배열엔 어떤 값의 목록이 들어갑니다. 이 배열을 특별히 종속성 배열이라고 부릅니다.
useEffect(함수, [종속성1, 종속성2, ...])
useEffect
의 두 번째 인자는 종속성 배열입니다. 배열 내의 종속성1, 또는 종속성2의 값이 변할 때, 첫 번째 인자의 함수가 실행됩니다.배열 내의 어떤 값이 변할 때에만, (effect가 발생하는) 함수가 실행됩니다.
만일 종속성 목록에 아무런 종속성도 없다면 어떤 일이 발생할까요? 달리 말해, 두 번째 배열을 빈 배열[]로 둘 경우에는 무슨 일이 발생할까요? 두 번째 인자를 아예 안 넘기는 것과 어떻게 다를까요?
빈 배열 넣기
useEffect(함수, [])
아무것도 넣지 않기 (기본 형태)
useEffect(함수)
2번 형태의 useEffect
는
1. 컴포넌트가 처음 생성되거나,
2. props가 업데이트되거나,
3. 상태(state)가 업데이트될 때 effect 함수가 실행됨을 앞서 배웠습니다.
반면에 1번 형태처럼 빈 배열을 useEffect
의 두 번째 인자로 사용하면,
이때에는 컴포넌트가 처음 생성될 때만 effect 함수가 실행됩니다. 이것이 언제 필요할까요?
대표적으로 처음 단 한 번, 외부 API를 통해 리소스를 받아오고 더 이상 API 호출이 필요하지 않을 때에 사용할 수 있습니다.