[React #24] COUNTER APP 만들기

반응형

01. 직접 짠 코드

📑 Header.jsx

const Header = () => { ​​return ( ​​​​<div> ​​​​​​<h1>Simple Counter</h1> ​​​​</div> ​​); }; export default Header;

 

📑 Viewer.jsx

import { useState } from "react"; const Viewer = () => { ​​const [count, setCount] = useState(0); ​​const countHandler = (e) => { ​​​​setCount(count + parseInt(e.target.innerText)); ​​}; ​​return ( ​​​​<div> ​​​​​​<p>현재 카운트 :</p> ​​​​​​<h3>{count}</h3> ​​​​​​<div> ​​​​​​​​<button onClick={countHandler}>-1</button> ​​​​​​​​<button onClick={countHandler}>-10</button> ​​​​​​​​<button onClick={countHandler}>-100</button> ​​​​​​​​<button onClick={countHandler}>+100</button> ​​​​​​​​<button onClick={countHandler}>+10</button> ​​​​​​​​<button onClick={countHandler}>+1</button> ​​​​​​</div> ​​​​</div> ​​); }; export default Viewer;

 

📑 App.jsx

import "./App.css"; import Header from "./components/Header"; import Viewer from "./components/Viewer"; import Controller from "./components/Controller"; function App() { ​​return ( ​​​​<div className="app"> ​​​​​​<Header /> ​​​​​​<Viewer /> ​​​​</div> ​​); } export default App;

실행화면

02. 수정 코드

 

📑 App.jsx

import "./App.css"; import Viewer from "./components/Viewer"; import Controller from "./components/Controller"; import { useState } from "react"; function App() { ​​const [count, setCount] = useState(0); ​​const countHandler = (value) => { ​​​​setCount(count + value); ​​}; ​​return ( ​​​​<div className="app"> ​​​​​​<h1>Simple Counter</h1> ​​​​​​<section> ​​​​​​​​<Viewer count={count} /> ​​​​​​</section> ​​​​​​<section> ​​​​​​​​<Controller countHandler={countHandler} /> ​​​​​​</section> ​​​​</div> ​​); } export default App;
  • section 태그로 컴포넌트를 묶는 이유 : 컴포넌트들마다 동일한 스타일을 주기 위함
  • App이 count 변수는 Viewr, setCount의 이벤트 핸들러는 Controller에게 전달

 

📑 App.css

body { ​​padding: 20px; } .app { ​​display: flex; ​​flex-direction: column; ​​gap: 10px; ​​width: 500px; ​​margin: 0 auto; } .app > section { ​​background-color: rgb(245, 245, 245); ​​border: 1px solid rgb(240, 240, 240); ​​border-radius: 5px; ​​padding: 20px; ​​margin-bottom: 10px; }

 

📑 Viewer.jsx

const Viewer = ({ count }) => { ​​return ( ​​​​<div> ​​​​​​<p>현재 카운트 :</p> ​​​​​​<h3>{count}</h3> ​​​​</div> ​​); }; export default Viewer;

 

📑 Controller.jsx

const Controller = ({ countHandler }) => { ​​return ( ​​​​<div> ​​​​​​<button ​​​​​​​​onClick={() => { ​​​​​​​​​​countHandler(-1); ​​​​​​​​}} ​​​​​​> ​​​​​​​​-1 ​​​​​​</button> ​​​​​​<button ​​​​​​​​onClick={() => { ​​​​​​​​​​countHandler(-10); ​​​​​​​​}} ​​​​​​> ​​​​​​​​-10 ​​​​​​</button> ​​​​​​<button ​​​​​​​​onClick={() => { ​​​​​​​​​​countHandler(-100); ​​​​​​​​}} ​​​​​​> ​​​​​​​​-100 ​​​​​​</button> ​​​​​​<button ​​​​​​​​onClick={() => { ​​​​​​​​​​countHandler(100); ​​​​​​​​}} ​​​​​​> ​​​​​​​​+100 ​​​​​​</button> ​​​​​​<button ​​​​​​​​onClick={() => { ​​​​​​​​​​countHandler(10); ​​​​​​​​}} ​​​​​​> ​​​​​​​​+10 ​​​​​​</button> ​​​​​​<button ​​​​​​​​onClick={() => { ​​​​​​​​​​countHandler(1); ​​​​​​​​}} ​​​​​​> ​​​​​​​​+1 ​​​​​​</button> ​​​​</div> ​​); }; export default Controller;

 

실행화면

 

 

 

 

POINT 1 ⭐

 

"데이터의 원천 state를 어떤 컴포넌트에 위치시킬지 생각하기"

 

특정값을 변경시켰을 때, 변경된 값을 컴포넌트가 화면에 바로 렌더링 하려면 state로 만들어야 하는데,

state는 컴포넌트 내부에서만 만들 수 있음

또한 props를 이용해서 값을 전달할 때는, 부모와 자식 관계에서만 가능하고,

형제 관계의 컴포넌트는 props를 이용해서 서로에게 값을 전달할 수 없음

 그래서 하나의 state를 여러 컴포넌트에서 관리하게 될 경우, 반드시 이 컴포넌트들의 공통 부모가 되는 곳에서 state를 만들어야 함

리액트의 계층 구조

 

여러 개의 컴포넌트들이 서로 부모와 자식 관계를 이루며 계층 구조를 형성하는데,

특정 컴포넌트가 다른 컴포넌트에게 데이터를 전달할 때는 반드시
두 컴포넌트는 서로 부모 자식 관계를 가지고 있어야 함
props를 이용하여 데이터 전달은 부모에서 자식 방향으로만 가능

✅ state Lifting : 계층 구조상에서 위로 끌어올려 아래에 있는 컴포넌트들이 모두 공유할 수 있는 방법
✅ 단방향 데이터 흐름 : 데이터의 흐름이 위에서 아래의 방향으로 흐르기 때문에 직관적임

 


POINT 2 ⭐

 

"함수와 함께 인수를 전달한다면 콜백 함수로 전달하기"

 

부모가 자식에게 props로 함수를 전달할 때, 인수도 전달하고 싶다면

함수 즉시 호출인 onClick={countHandler}onClick={countHandler(-10)}  대신

콜백 함수를 사용하여 onClick={()=>{countHandler(10}} 이렇게 전달해야 함

→ countHandler 함수를 이벤트 핸들러로 설정하고 해당 이벤트 헨들러에서 함수를 호출한 뒤 원하는 값의 인수를 넘겨야 함

 

 

 

 

참고자료

이정환 Winterlood, '한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지'
반응형