상태 끌어올리기가 필요한 경우
하위 컴포넌트에서 발생한 어떤 이벤트에 의해 상위 컴포넌트의 상태가 변경되어야 할때
리액트는 데이터가 부모 컴포넌트에서 자식 컴포넌트로 단방향으로 (Top to Bottom) 흐른다.
만약, 자식 컴포넌트의 어떤 이벤트에 의해 부모 컴포넌트의 상태가 바뀐다면, 역방향으로 데이터가 흐르고 이는 리액트의 단방향 흐름 원칙에 위배되는 걸까?
리액트에서는 단방향 흐름의 원칙을 지키면서, 자식 컴포넌트에서 부모 컴포넌트로 데이터를 보내기 위해 (Bottom to Top)한 방법으로 상태 끌어올리기라는 방법을 제시한다.
그 방법은 부모 컴포넌트의 상태 변화함수를 자식 컴포넌트에 인자로 전달하고 자식 컴포넌트에서 그 함수를 실행시켜 부모 컴포넌트의 상태를 변화시키는 것이다.
좀 더 쉽게 이해하기 위해 예시를 살펴보도록 하자.
ChildComponent onBtnclick = {handleChange}
부모 컴포넌트에서 자식 컴포넌트로 props를 전달하는데, 키는 onBtnClick, 값은 상태변화함수이다 (단방향 데이터 흐름 충족)
function ChildComponent({onBtnClick}){}
자식 컴포넌트의 인자로 상태변화 함수가 전달되었다
return <button onClick = {handleClick}>값 변경</button>
버튼이 클릭되었을때 handleClick 함수가 동작하는데, 해당 함수는 인자로 전달받은 함수를 작동시키는 함수이다
따라서, 정리해보자면, 자식 컴포넌트에서 버튼을 클릭하면 이벤트 핸들러(handleClick)가 실행되는데, 그 핸들러는 자식 컴포넌트가 인자로 입력받은 함수 (콜백함수, 부모 컴포넌트의 상태변화함수)를 동작시키고, 그 결과 부모 컴포넌트의 상태가 업데이트 된다!
데이터 흐름
상위 컴포넌트(Twittler)는 상태(tweets)를 갖고, 하위 컴포넌트 (NewTweeTForm)에서 글을 작성하고 새글쓰기 버튼을 클릭하면 상위 컴포넌트의 상태인 tweets가 업데이트 된다.
<NewTweetForm onButtonClick = {addNewTweet} />
단방향 데이터 흐름의 원칙을 지키고 상태를 끌어올리기 위해 상태변경함수가 하위 컴포넌트에 props로 전달된다.
const addNewTweet = (newTweet) => { setTweets([...tweets, newTweet])}
addNewTweet 함수는 인자로 새로 생성된 트윗(객체)을 입력받아 spread syntax를 사용해 하나의 배열에 기존 트윗들과 함께 담아준다.