[React] useState , useEffect๐Ÿ‘พ

Joyยท2022๋…„ 6์›” 16์ผ
0

React

๋ชฉ๋ก ๋ณด๊ธฐ
1/1
post-thumbnail
post-custom-banner

๋ฆฌ์•กํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ  ์ฑ…์„ ์Šคํ„ฐ๋””ํ•˜๋ฉฐ ์ •๋ฆฌํ•˜๋Š” ๊ธ€์ž…๋‹ˆ๋‹ค.

  • useState , useEffect๋ฅผ ์‚ฌ์šฉํ•œ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ 2๊ฐ€์ง€๋ฅผ ์ •๋ฆฌํ•ด๋ณด์ž.

๐Ÿš€ useState

1. ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ์ˆซ์ž ์นด์šดํ„ฐ ์˜ˆ์ œ

// Counter.js ํŒŒ์ผ์— ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•ด์ค€๋‹ค.

import React, { useState } from "react";

const Counter = () => {
  // ๊ธฐ๋ณธ๊ฐ’์€ 0์œผ๋กœ ์„ค์ •.
  const [value, setValue] = useState(0);

  return (
    <div>
      <p>
        ํ˜„์žฌ ์นด์šดํ„ฐ ๊ฐ’์€ <b>{value}</b>์ž…๋‹ˆ๋‹ค.
      </p>
      // ์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฐ’์ธ setValue๋ฅผ ๋„ฃ์–ด์ฃผ๊ณ  ์ƒํƒœ๊ฐ’์—์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค€๋‹ค.
      <button onClick={() => setValue(value + 1)}>+1</button>
      <button onClick={() => setValue(value - 1)}>-1</button>
    </div>
  );
};

export default Counter;

๋จผ์ € Counter๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด์ค€ ๋’ค setValue๋ผ๋Š” useState ๊ฐ’์„
์„ ์–ธํ•ด์ฃผ๊ณ  useState์˜ ํ•จ์ˆ˜ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ๊ธฐ๋ณธ๊ฐ’(0)์„ ๋„ฃ์–ด์ค€๋‹ค.

์ด ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ๋ฐฐ์—ด์ด ๋ฐ˜ํ™˜๋˜๊ณ  ๊ทธ ๋ฐฐ์—ด์˜ ์ฒซ๋ฒˆ์งธ ์›์†Œ๋Š” ์ƒํƒœ ๊ฐ’ , ๋‘๋ฒˆ์งธ ์›์†Œ๋Š”
์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฐ’์ด ๋˜๋Š”๊ฒƒ์ด๋‹ค. ์ด ํ•จ์ˆ˜์— ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„ฃ์–ด ํ˜ธ์ถœํ•˜๋ฉด ์ „๋‹ฌ๋ฐ›์€ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ
๊ฐ’์ด ๋ฐ”๋€Œ๊ณ  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋ฆฌ๋ Œ๋”๋ง ๋œ๋‹ค๊ณ  ํ•œ๋‹ค.

๊ทธ๋ž˜์„œ value ๊ฐ’์€ ๊ธฐ๋ณธ๊ฐ’์ธ 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ณ  +1์ธ ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ์‹œ ์ˆซ์ž๊ฐ€ ํ•˜๋‚˜์”ฉ
๋Š˜์–ด๋‚˜๊ณ  -1์ธ ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ์‹œ๋Š” ์ˆซ์ž๊ฐ€ ํ•˜๋‚˜์”ฉ ์ค„์–ด๋“œ๋Š”๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

2. useState ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•˜๊ธฐ

import React, { useState } from "react";

const Info = () => {
  const [name, setName] = useState("");
  const [nickname, setNickname] = useState("");

  const onChangeName = (e) => {
    setName(e.target.value);
  };

  const onChangeNickname = (e) => {
    setNickname(e.target.value);
  };

  return (
    <>
      <div>
        <input value={name} onChange={onChangeName} />
        <input value={nickname} onChange={onChangeNickname} />
      </div>

      <div>
        <div>
          <b>์ด๋ฆ„: </b>
          {name}
        </div>
        <div>
          <b>๋‹‰๋„ค์ž„: </b>
          {nickname}
        </div>
      </div>
    </>
  );
};

export default Info;

์ด ์˜ˆ์ œ๊ฐ™์€ ๊ฒฝ์šฐ ์ด๋ฆ„์„ ์ €์žฅํ•˜๋Š” state ๊ฐ’๊ณผ ๋‹‰๋„ค์ž„์„ ์ €์žฅํ•˜๋Š” state ๊ฐ’ 2๊ฐœ๋ฅผ ๋งŒ๋“ค์—ˆ๋Š”๋ฐ
๋จผ์ € onChangeName์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•ด์ค€ ๋’ค -> ์ƒํƒœ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฐ’์ธ setName์—
์ด onChange ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ ๋Œ€์ƒ ๊ฐ’์„ ๋‹ด์•„์ฃผ๊ณ  -> ๊ฐ’์ด ๋“ค์–ด์˜ค๋Š” input ํƒœ๊ทธ์—
value ๊ฐ’์„ ์ฒซ๋ฒˆ์งธ ์›์†Œ์ธ name ์ฆ‰, ํ˜„์žฌ ์ƒํƒœ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๊ณ 

"onChange๊ฐ€ ๋์„ ๊ฒฝ์šฐ ์ด ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด์ฃผ์„ธ์š”!"

๋ผ๊ณ  ์„ ์–ธํ•ด์ฃผ๋ฉด input์— ๋„ฃ๋Š” ๊ฐ’์ด ์•„๋ž˜ div ํ…์ŠคํŠธ์— ์ž˜ ๋“ค์–ด๊ฐ€ ์žˆ๋Š”๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค!

๐Ÿš€ useEffect

useEffect(() => {
    console.log("๋ Œ๋”๋ง์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!");
    console.log({
      name,
      nickname,
    });
  });

  useEffect(() => {
    console.log("effect");
    console.log(name);
    return () => {
      console.log("cleanup");
      console.log(name);
    };
    // ํ•˜๋‹จ [name] ๋ถ€๋ถ„์ด ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐฐ์—ด๊ฐ’์ด๋‹ค.
  }, [name]); 

์ผ๋‹จ useEffect๋ž€ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š”
Hook์ด๋‹ค. ์•„๊นŒ ์‹คํ–‰ํ–ˆ๋˜ ์˜ˆ์ œ์— useEffect๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•Œ์•„๋ณด๋„๋ก ํ•˜์ž.

์ฒซ๋ฒˆ์งธ useEffect ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์•„๊นŒ ์ฒ˜๋ฆฌํ•ด๋‘์—ˆ๋˜ name๊ณผ nickname์„ ์ฝ˜์†”์— ์ถœ๋ ฅํ•˜๊ฒŒ ๋˜๋ฉด ๋‚ด๊ฐ€ input์— ๊ฐ’์„ ์ ์„๋•Œ๋งˆ๋‹ค ์ฝ˜์†”์— ์ฐํžˆ๋Š”๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
-> ์—…๋ฐ์ดํŠธ ๋ ๋•Œ๋งˆ๋‹ค ์‹คํ–‰์ค‘.

๋‘๋ฒˆ์งธ useEffect ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ๋งˆ์šดํŠธ๋  ๋•Œ๋งŒ ์‹คํ–‰ํ•˜๊ณ ์ž ํ•˜๋Š”๊ฑด๋ฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งจ ์ฒ˜์Œ ๋ Œ๋”๋ง ๋  ๋•Œ๋งŒ ์‹คํ–‰ํ•˜๊ณ  , ์—…๋ฐ์ดํŠธ ๋ ๋•Œ๋Š” ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ์ž ํ•˜๋ฉด ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋น„์–ด์žˆ๋Š” ๋ฐฐ์—ด์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋˜๋Š”๊ฒƒ์ด๋‹ค!
๊ทธ๋Ÿฌ๋ฉด ์ฒ˜์Œ ์ƒˆ๋กœ๊ณ ์นจ์„ ํ–ˆ์„๋•Œ๋งŒ ์ฝ˜์†”์— ์ฐํžˆ๋Š”๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
-> ๋งจ ์ฒ˜์Œ ๋ Œ๋”๋ง ๋ ๋•Œ๋งŒ ์‹คํ–‰.

์ฆ‰ useEffect๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ Œ๋”๋ง์ด ๋œ ์งํ›„๋งˆ๋‹ค ์‹คํ–‰๋˜๋Š”๋ฐ ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋ฌด์—‡์„
๋„ฃ๋Š”์ง€์— ๋”ฐ๋ผ ์‹คํ–‰๋˜๋Š” ์กฐ๊ฑด์ด ๋‹ฌ๋ผ์ง€๋Š”๊ฒƒ์ด๋‹ค. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ ๋˜๊ธฐ ์ „์ด๋‚˜ ์—…๋ฐ์ดํŠธ
๋˜๊ธฐ ์ „์— ์–ด๋– ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋’ท์ •๋ฆฌ(cleanup) ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

+ ์ถ”๊ฐ€ ์˜ˆ์ œ

const Info = () => {
  const [visible, setVisible] = useState(false);
  
  useEffect(() => {
    console.log("effect");
    return () => {
      console.log("cleanup");
    };
  }, []);
  
  return (
    <>
      <div>
        <button type="button" onClick={() => setVisible(!visible)}>
          {visible ? "์ˆจ๊ธฐ๊ธฐ" : "๋ณด์ด๊ธฐ"}
        </button>
        {visible && <Info />}
      </div>
    </>
  );
};

์ด ์˜ˆ์ œ๋Š” button ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•ด ๋ณด์ด๊ธฐ ๋ฒ„ํŠผ์„ ํด๋ฆญ์‹œ Info ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‚˜ํƒ€๋‚˜๊ณ  ๋ณด์ด๊ธฐ ๋ฒ„ํŠผ์ด
์ˆจ๊ธฐ๊ธฐ ๋ฒ„ํŠผ์œผ๋กœ ๋ฐ”๋€Œ๊ฒŒ ๋œ๋‹ค. visible์˜ ๊ธฐ๋ณธ๊ฐ’์ด false๋กœ ๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— false์ผ ๊ฒฝ์šฐ ๋ณด์ด๊ธฐ ๋ฒ„ํŠผ์ด ๋จผ์ € ๋‚˜์˜ค๊ฒŒ ๋˜๊ณ  ์ด ๋ฒ„ํŠผ์„ ํด๋ฆญํ•  ์‹œ false -> true ๊ฐ’์œผ๋กœ ๋ณ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ˆจ๊ธฐ๊ธฐ ๋ฒ„ํŠผ์ด ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์ด ์˜ˆ์ œ๋Š” ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค ๋’ท์ •๋ฆฌ ํ•จ์ˆ˜๊ฐ€ ๊ณ„์† ๋‚˜ํƒ€๋‚˜๋Š”๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ณ  ๋’ท์ •๋ฆฌ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ๋Š” ์—…๋ฐ์ดํŠธ
๋˜๊ธฐ ์ง์ „์˜ ๊ฐ’์„ ๋ณด์—ฌ์ค€๋‹ค.

์˜ค์ง ์–ธ๋งˆ์šดํŠธ๋  ๋•Œ๋งŒ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๊ผญ ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋นˆ ๋ฐฐ์—ด์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋˜๋Š”๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿผ ์ด๋ ‡๊ฒŒ ๋ณด์ด๊ธฐ๋ฅผ ํด๋ฆญ์‹œ Info ์ปดํฌ๋„ŒํŠธ์— ์žˆ๋˜ ์ปจํ…์ธ ๊ฐ€ ๋‚˜ํƒ€๋‚˜๊ณ  ์ฝ˜์†”์—๋„ ๋‚˜ํƒ€๋‚ ๋•Œ effect์™€
์‚ฌ๋ผ์งˆ๋•Œ cleanup ํ…์ŠคํŠธ๊ฐ€ ์ฐํžˆ๋Š”๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

๋ฆฌ์•กํŠธ์—์„œ ์ˆ˜๋„ ์—†์ด ์“ฐ์ด๋Š” useState์™€ useEffect๋ฅผ ์˜ˆ์ œ์™€ ํ•จ๊ป˜ ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค.
์—ญ์‹œ ๊ทผ๋ณธ์€ ๊ธฐ๋ณธ๊ธฐ๋ฅผ ํƒ„ํƒ„ํ•˜๊ฒŒ ์Œ“๋Š”๊ฑฐ์ง€! โœŠ

profile
์ƒˆ๋กœ์šด ๊ฑฐ์— ์ง„์‹ฌ์ธ ์‚ฌ๋žŒ
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€