상세 컨텐츠

본문 제목

React(리액트) 티키타카 11 ( useState Hook)

React

by e7e 2024. 10. 7. 20:23

본문

2024.10.03 - [React] - React(리액트) 티키타카 10 (레이아웃, children )

까지 읽었다면, 아마 불현듯 머릿속에 머얌 정작 화면 만들기만 하공

이벤트등 알짜는 아직 업쟈녀~~ 라는 공격적 응원이 생길만 하당.

 

맞당. 이제  저 유명한 거의 모든 React책이나, 사이트등에서 맹그는 카운터 예제

조금 더 심플하게 맹글어 볼 때가 되었당.  중요한 부분이니 고도로 집중하여 보장.

 

아래 코드를 작성해 보장. (풀린 눈 말고,조금은 집중된 눈으로 코드를 읽자)

 

Counter.css

.counter {
    width:70%;
    min-width:300px;
    border:5px groove orange;
    margin:50px auto;
}

.counter > h2 {
    color:blueviolet;
}
.counter > h1 {
    color: red;
    font-size: 4em;
}

 

 Counter.jsx

import PropsType from "prop-types";
import "./Counter.css";

Counter.propTypes = {
  title: PropsType.string.isRequired,
};

function Counter({ title }) {
  console.log("체킁:", "경민 만세 호출됨");

  // 카운트 변수
  let myCount = 0;

 // 클릭 이벤트 처리 함수(이벤트 핸들러)
  const fCnt = () => {
    alert("console을 띠우삼");
    myCount++;
    console.log("체킁:", "미누 안만세");
  };

  return (
    <div onClick={fCnt} className="counter">
      <h2>{title}</h2>
      <hr />
      <h1>{myCount}</h1>
    </div>
  );
}

export default Counter;

onclick 이 아니공, onClick임에 주의하장. html이 아니공, 한번 더 해석되는 JSX당.

 

App.jsx  (결과 확인용)

import Counter from "./Counter";

function App() {
  return (
    <div>
      <Counter title={"경민 클릭 카운터"} />
    </div>
  );
}

export default App;

 

결과는 조작하지 않았다면 아래와 같을지어당.

[ console의 경민 만세 호출됨 부분을 꼭 기억해 두장 ]

클릭해도 당연히 화면에 보이는 숫자는 계속 0 이당.

 

자바스크립트를 꽤 아는 사람은 바로 

 Counter.jsx 를  아래 처럼 수정 하고 기뻐할꺼이 뻔하당.

import PropsType from "prop-types";
import "./Counter.css";

Counter.propTypes = {
  title: PropsType.string.isRequired,
};

function Counter({ title }) {
  console.log("체킁:", "경민 만세 호출됨");

  let myCount = 0;

  const fCnt = () => {
    alert("console을 띠우삼");
    myCount++;
    console.log("체킁:", "미누 안만세");

    /* 추가한 부분 */
    document.querySelector(".aaa").innerHTML = myCount;
  };

  return (
    <div onClick={fCnt} className="counter">
      <h2>{title}</h2>
      <hr />
      { /* class aaa 추강 */ }
      <h1 className="aaa">{myCount}</h1>
    </div>
  );
}

export default Counter;

 

결과는 아래 처럼 잘 될게 뻔하당. [ console의 경민 만세 호출됨 부분을 꼭 기억해 두장 ]

 

하지만 너무 눈물 홍수! 공감 가뭄!이게동 ~ 이거슨 React가 원하는 모습이 아니었당.

[ 이 방식을 개선하려 했던 거시 였던 거시였는데 요따구로 쓰면 그저 참당할뿌니당~ ㅋㅋ]

그랬당.  여기서 React는 useState라는 Hook을 쓰라 한당.  일단 먼저 써보장.

 

 Counter.jsx 에 useState Hook을 적용하여 수정하장.

import PropsType from "prop-types";
import "./Counter.css";

/* 추가 된 부분 */
import { useState } from "react";

Counter.propTypes = {
  title: PropsType.string.isRequired,
};

function Counter({ title }) {
  console.log("체킁:", "경민 만세 호출됨");

  /* 바뀐 부분 */
  const [myCount, setMyCount] = useState(0);

  const fCnt = () => {
    alert("console을 띠우삼");
    setMyCount((myCount) => myCount + 1); // 바뀐 부분
    console.log("체킁:", "미누 안만세");
  };

  return (
    <div onClick={fCnt} className="counter">
      <h2>{title}</h2>
      <hr />
      <h1>{myCount}</h1>
    </div>
  );
}

export default Counter;

 

결과는 이전과 같은 데엥, console에 찍힌 게 먼가 의미 심장하당.

클릭 할때마당, 경민 만세 호출됨이 console에 찍힌당.  무신 의미 일깡?

Counter 함수가 통째로 다시 불렸다는 의미는? ....  곰곰... 아!!!~~ Counter 컴포넌트가 다시

만들어졌다는, 곧 다시 그려졌다는(re-rendering 되었다는) 의미당. (오켕?.. 아직 애맹?)

 

모르면 안드로메다 이야기공, 알면 새끼 발가락 티눈처럼 뽑아버리고 싶당.

자주 사용되는 아래 형식을 기억하장.  React에서 제공하는 useState Hook(훅) 사용법이당.

const [myCount, setMyCount] = useState(0);
//           변수명      ,함수명           =  useState(초기값)

myCount는 변수명이고 setMyCount는 myCount 변수에 값을 세팅하는 함수인데,

관례적으로 set변수명(변수명 첫글짜는 대문자)으로 정하고, useState의 ()안의 값은

myCount 변수의 초기값이당.  애매스럽다면 일단 사용법 기억만으로 만족해도 괘않탕.

 

useState로 사용한 myCount 같은 변수를 React에선 멋진 말로 Reactive 변수라 

일컫는뎅, 이 값이 바뀌게 되면 React는 해당 컴포넌트를 다시 그린당.

[타짜 손보다 빨라 웬만해선 눈으로 볼 수 없당. ]

 

자바스크립트를 공부한 흔적을 꽤나 쌓은 사람이라면 위의 형식이 구조분해가 

사용된 형식임을 본능적으로 졸다가도 느끼미 온당.  아래 코드 눈으로 휘릭 느낌만 받장.

  // useState 사용이 구조분해임을 보여주는 심플 가짜코드

  function useState(initV) {
    // 배열에 값과 함수를 담아서 리턴
    return [initV, function () {}];
  }

  const [count, setCount] = useState(0);

 

React에서 제공하는 Hook(훅) 함수들의 공통점은 앞에 use를 붙여서 사용하기 때문에 

금방 알아챌 수 있당. 그럼 Hook 함수란 무엇인가?

 

Hook 함수 덕분에 class 키워드 사용이 거의 필요없공function 컴포넌트로 편하게 

바뀌게 되었는뎅,  Hook은 버젼 16.8 부터 추가 되었당.

컴포넌트의 상태값에도 접근할 수 있고, 컴포넌트가 새로 html문서에 붙거나(mount)

사라지거나(unmount) 등의 이벤트 처리등도 Hook 함수로 편하게 처리 할 수 있당.

이 시점에선 그냥 React에서 제공해 주는 편리한 함수정도로 일단 만족하장!

 

여기서 뇌를 쪼금 자극하는 방향으로 한발짝 더 나아가 보장.

 

App.jsx   일부러 여기서 시작한거당. top -> down 흐름이 보이겡

import { useState } from "react";
import Counter from "./Counter";

function App() {
  const [sum, setSum] = useState(0);

  return (
    <div>
      <Counter title={"경민 클릭 카운터"} fsum={setSum} />
      <Counter title={"미누 클릭 카운터"} fsum={setSum} />
      <Counter title={"선주 클릭 카운터"} fsum={setSum} />
      <h1>
        모두의 클릭수는 {sum} 이당
      </h1>
    </div>
  );
}

export default App;

위 코드를 보면 바로 눈치 채겠지만 . 각각의 Counter를 클릭한 수를 합한

sum을 추가로 표시할 생각이당.

Counter의  Props의 속성명 fsum으로 setSum  함수를 넘겼당. 

 

Counter.jsx 도 위에 맞게 당연히 수정되어야 한당.

import PropsType from "prop-types";
import "./Counter.css";

/* 추가 된 부분 */
import { useState } from "react";

Counter.propTypes = {
  title: PropsType.string.isRequired,
  fsum: PropsType.func.isRequired,   // 추가된 부분
};

function Counter({ title, fsum }) {   // 바뀐 부분
  console.log("체킁:", "경민 만세 호출됨");

  /* 바뀐 부분 */
  const [myCount, setMyCount] = useState(0);

  const fCnt = () => {
    alert("console을 띠우삼");
    setMyCount((myCount) => myCount + 1); 
    console.log("체킁:", "미누 안만세");
    fsum((sum) => sum + 1);                // 추가된 부분
  };

  return (
    <div onClick={fCnt} className="counter">
      <h2>{title}</h2>
      <hr />
      <h1>{myCount}</h1>
    </div>
  );
}

export default Counter;

 

결과를 눈으로 확인하장.~~(각각 클릭해 보면 잘 되리랑!)

 

정리를 조금 해보장.

fCnt 함수안에서 fsum(실제는 setSum함수를 가리킴)을 이용하여

원래 가진 sum값을 +1씩 증가 시킨당.

useState가 return하는 setXXX함수의 매개변수 콜백함수  preVal => preVal +1 의 

매개변수 preVal은 바로 이전 상태의 값을 가지고 있당.

(받아들이장.. 그렇게 설계 되었당.. 시르면 본인만 힘들당.~~  )

아래 내용은 설마하는 노파심에 적어본당.~~ (화살표 함수 알디용?)

/* 
  아래 fCk1과 fCk2는 같은 의미다.
*/
const fCk1 = preVal => preVal+1

function fCk2(preVal){
    return preVal + 1;
}

 

fsum: PropsType.func 단지 fsum은 함수타입이어야 한다는 의미당.

 

간단한 예제지만 의미는 아주 아주 중요하당.( 쪼메라도 감을 잡아보장) 

정보는 부모에게서 자식 방향으로만 흐른다고 초반에 꼬옥 기억하라 하였당.

지금 sum값을 출력하는 것은 App에 있고, 이벤트 발생은 Counter에 있당.

자식 컴포넌트의 이벤트로 부모안의 값을 바꾸었당.(거꾸로당...훌륭하당!~~  오켕?? )

그리고 기억하랑.

부모의 상태가 바뀌고 다시 그려지게 되면 자동으로 자식도 다시 그려진당.

 

 

어쩌면 무언가 느끼미 부족한 사람이 있을지도 모르겠당.

괜찮당.

원래 안다고 생각했는데,

나중에 보면 부족했음을 느낀당. 

아마도 내가 이 글을 낸 중에 읽으면 이게 머얌! 할거당.

 

다음 글에서 만날 수는 있을깡?~~

 

 


요즘 나의 가장 부러움을 사는 단어는 자숙이당.

 

자숙은 해방이었으며!

 

자숙은  또 휴식이었으며!

 

자숙은 또한 의무없는 소득의 의미였당.

 

왜?  이걸 이제야 알게 되었을까?

 

자숙에 대한 부러움으로  난 이미  오래전 부터

 

삶에 속아온 바보같은  Lonely Heart 당.

 

당신은 자숙에 대한 나의 평가를 이해 할 수 없을거시당. 

 

그래서 더 외롭도록 외로운 띰장!

 

https://www.youtube.com/watch?v=CskZPy8nTN8

 

관련글 더보기