React의 데이터 흐름은 상위 컴포넌트에서 하위 컴포넌트로 전달하는 하향식, 단방향 데이터 흐름이다.
기능 변경 사항에 대한 코드 수정이 적다거나 코드의 흐름을 알기 쉽다는 장점이 있지만 한 부모 아래에 있는 자식 컴포넌트끼리 state 공유가 불가능하다는 단점이 있다. 다만 state lifting을 사용하면 이를 보완할 수 있다.
컴포넌트 간 state를 공유하는 경우, 컴포넌트 간 가장 가까운 공통 부모 컴포넌트로 state를 끌어 올리고 props를 통해 자식 컴포넌트로 불러주면 된다.
동일한 데이터에 대한 변경 사항을 여러 컴포넌트에 반영해야 할 경우 사용한다.
또한 부모 컴포넌트에서 자식 컴포넌트로 setState까지 넘겨주어 자식컴포넌트에서 state를 관리할 수 있다는 것이 핵심이다.
state 끌어올리기를 사용해서 규모가 큰 하나의 컴포넌트를 여러 개의 자식 컴포넌트로 분리해서 만들 수 있다. 이렇게 컴포넌트를 분리함으로써, 컴포넌트의 길이를 획기적으로 줄일 수 있다.
// 부모 컴포넌트
import { useState } from "react";
import Child1 from "../../../src/components/units/15-lifting-state-up/Child1";
import Child2 from "../../../src/components/units/15-lifting-state-up/Child2";
export default function CounterState(): JSX.Element {
const [count, setCount] = useState(0);
// let count = 0 let은 리액트 전용 html에서 변경을 감지하지 못 함 따라서 state를 써야함 //
function onClickCountUp(): void {
setCount(count + 1);
}
return (
<div>
<Child1 count={count} setCount={setCount} />
<div>=============================</div>
<Child2 count={count} onClickCountUp={onClickCountUp} />
</div>
);
}
// 자식1 컴포넌트
export default function Child1(props: any): JSX.Element {
const onClickCountUp = (): void => {
props.setCount((prev: number) => prev + 1);
};
return (
<div>
<div>Child1 count: {props.count}</div>
<button onClick={onClickCountUp}>카운트 올리기</button>
</div>
);
}
// 자식2 컴포넌트
export default function Child2(props: any): JSX.Element {
return (
<div>
<div>Child2 count: {props.count}</div>
<button onClick={props.onClickCountUp}>카운트 올리기</button>
</div>
);
}