카운트 기능을 구현하기에 앞서
State를 사용하는 위치에 대해생각해 볼 필요가 있다.
우리가 만들고 있는 카운터 앱은 총 세 가지의 컴포넌트를 가진다.
현재 카운트를 화면으로 보여주는 Viewer
카운트를 조작하는 Controller
그리고 두 컴포넌트를 감싸고 있는 App 이다.

그렇다면
State를 사용해야하는 곳은 어딜까?결론부터 말하자면 App.jsx 쪽이다.
컨트롤러에서 클릭 이벤트로 변경되는 값을 받아서
뷰어에 전달하여 리랜더링을 발생시켜야 하는데,
부모자식 관계가 아닌 형제 관계에서는 이를 전달할 수 없다.
따라서 App에서
props를 사용하여 상태를 관리해야 하는 것이다.
1. App 컴포넌트에서 State 선언 및 관리
이제 기능을 만들어보자.
먼저,
useState를 사용할 수 있도록 import 하고Viewer 컴퍼넌트에
count 라는 props로 count를 전달하자.import "./App.css";
import Controller from "./components/Controller";
import Viewer from "./components/Viewer";
import { useState } from "react";
function App() {
const [count, setCount] = useState(0);
return (
<div className="App">
<h1>Simple Counter</h1>
<section>
<Viewer count={count} />
</section>
<section>
<Controller />
</section>
</div>
);
}
export default App;
2. Viewer에서 props를 통해 상태 값 표시
그러고 난 다음 이를 전달받는 화면인
Viewer에서
props로 받아 사용할 수 있게 하자.const Viewer = ({ count }) => {
return (
<>
<div>
<p>현재 카운트 :</p>
<h1>{count}</h1>
</div>
</>
);
};
export default Viewer;3. 상태 변경을 위한 이벤트 핸들러 정의
다음으로는 이벤트를 발생시키는 Controller 상태관리를 해보자.
Controller에는 이벤트 핸들러를 만들기 위해
count와 setCount 둘 다props로 넘겨주어야 한다.그래서 이 둘을 넘기기 보다는 이벤트 핸들러를 해당하는 컴퍼넌트의 외부인,
즉 App.jsx 위치에서 만들어 눌러진 버튼의 값만 부모로 전달하여 부모에게서
이벤트를 발생시키는 것이 편리하다.
먼저, 이벤트 핸들러부터 만들어보자.
import "./App.css";
import Controller from "./components/Controller";
import Viewer from "./components/Viewer";
import { useState } from "react";
function App() {
const [count, setCount] = useState(0);
const onClickButton = (value) => {
setCount(count + value);
};
return (
<div className="App">
<h1>Simple Counter</h1>
<section>
<Viewer count={count} />
</section>
<section>
<Controller />
</section>
</div>
);
}
export default App;
컨트롤러에서 받아올 값을
count에 더해 주기만 하는간단한 이벤트 핸들러를 만들 수 있다.
4. Controller에서 props로 이벤트 전달받기
다음으로 이러한 이벤트 핸들러 자체를
props로Controller 컴퍼넌트에 넘겨주자.
<Controller onClickButton={onClickButton} />컨트롤러에서는
onClickButton을 props로 받아각 버튼의 onClick 이벤트에 사용할 수 있다.
익명함수에 onClickButton 이벤트를 넣고,
매개변수로 각 버튼을 클릭했을 때 해당하는 이벤트로
넘길
value 값을 작성해주자.const Controller = ({ onClickButton }) => {
return (
<div>
<button
onClick={() => {
onClickButton(-1);
}}
>
-1
</button>
<button
onClick={() => {
onClickButton(-10);
}}
>
-10
</button>
<button
onClick={() => {
onClickButton(-100);
}}
>
-100
</button>
<button
onClick={() => {
onClickButton(+100);
}}
>
+100
</button>
<button
onClick={() => {
onClickButton(+10);
}}
>
+10
</button>
<button
onClick={() => {
onClickButton(+1);
}}
>
+1
</button>
</div>
);
};
export default Controller;
5. State Lifting과 단방향 데이터 흐름 정리
리액트에서 상태 관리를 하기 위해서는 오늘 실습을 관통하는
개념을 이해할 필요가 있다.
State Lifting은 여러 컴포넌트가 같은 상태를 사용해야 할 때,
그 상태를 공통 부모 컴포넌트로 올려 관리하는 것이다.
리액트는 단방향 데이터 흐름 구조이기 때문에
데이터는 항상 부모 → 자식 방향으로만 전달된다.
따라서 형제 컴포넌트가 상태를 공유하려면
공통 부모에서 state를 관리하고
props로 내려주어야 한다.


Share article