React Hooks (๊ธฐ๋ณธ)

๋ฆฌ์•กํŠธ ํ›…์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์˜ ๊ธฐ๋Šฅ(์ƒํƒœ๊ฐ’, ์ƒ๋ช…์ฃผ๊ธฐ ๋“ฑ)์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. ํ›…์€ ๋‹จ์ˆœํ•œ ํ•จ์ˆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์†์‰ฝ๊ฒŒ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜ ์žˆ๊ณ , ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ณ€ํ™”์œจ ํ˜น์€ ๊ด€๋ จ๋„์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋ผ์ดํ”„์‚ฌ์ดํด์— ๋ฌถ์—ฌ ์—ฌ๋Ÿฌ์ฝ”๋“œ๊ฐ€ ๋’ค์—‰์ผœ ์ž‘์„ฑ๋˜์–ด์•ผ ํ–ˆ๋˜๊ฒƒ๊ณผ ๋‹ฌ๋ฆฌ, ํ›…์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ถ„๋ฆฌ ๋ฐ ๊ด€๋ฆฌํ•˜๊ธฐ์— ์šฉ์ดํ•˜๋‹ค.(Information Expert) ์ด๋ฅผ ํ†ตํ•ด ํ•„์š”ํ•œ ๋กœ์ง๊ณผ ์ƒํƒœ๋ฅผ ์บก์Šํ™”(capsulization)ํ•˜์—ฌ ์ปค์Šคํ…€ ํ›…์„ ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜๋„ ์žˆ๋‹ค. (useDebounce ํ›…) ์ด๋ฏธ ๋งŽ์€ ๋ฆฌ์•กํŠธ ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ํ›…์„ ์ง€์›ํ•˜๊ณ  ์žˆ๋‹ค.


ํ›…์„ ์ดํ•ดํ•˜๋Š”๋ฐ ๋งํฌ์—์„œ ์†Œ๊ฐœํ•˜๋Š” ๊ฐ„๋‹จํ•œ React Hooks ๋ณต์‚ฌ๋ณธ ์ฝ”๋“œ๋ฅผ ๋”ฐ๋ผํ•ด ๋ณด๋Š”๊ฒƒ์ด ์ดํ•ด์— ๋งŽ์€ ๋„์›€์ด ๋˜์—ˆ๋‹ค. ๋‚ด์šฉ์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํด๋กœ์ €์— ๋Œ€ํ•œ ๊ธฐ๋ณธ์ ์ธ ์ง€์‹์ด ํ•„์š”ํ•˜๋‹ค.


useState

useState ํ›…์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ๊ฐ’์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

import React, { useState } from 'react';

useState ํ›…์€ ์–ด๋–ค ๊ฐ’์„ ๋ฐ›์•„ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋‹จ์ˆœํ•œ ํ•จ์ˆ˜์ด๋‹ค. ๋ฐฐ์—ด์˜ ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋Š” ์ƒํƒœ๊ฐ’์ด๊ณ  useState๋ฅผ ํ˜ธ์ถœํ• ๋•Œ ๋„˜๊ฒจ์ค€ ๊ฐ’์ด ์ดˆ๊ธฐ๊ฐ’์ด ๋œ๋‹ค. ๋ฐฐ์—ด์˜ ๋‘๋ฒˆ์งธ ์š”์†Œ๋Š” setState ๋ฉ”์†Œ๋“œ์™€ ์œ ์‚ฌํ•œ ์ƒํƒœ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋‘ ์š”์†Œ๋ฅผ ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น(Destructuring Assignment)์„ ํ†ตํ•ด ๋ณ€์ˆ˜์— ํ• ๋‹นํ•ด ์‚ฌ์šฉํ•œ๋‹ค.

const Counter = () => {
  const [count, setCount] = useState(0); // ๋ฐฐ์—ด์˜ ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น

  const handleCount = e => {
    e.preventDefault();
    setCount(count + 1);
  }

  return(
    <button onClick={handleCount}>{count}</button>
  );
}

๋‹ค์ˆ˜์˜ ์ƒํƒœ ๊ด€๋ฆฌ

useState ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์ƒํƒœ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์ˆ˜์˜ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

const Person = () => {
  const [age, setAge] = useState(0);
  const [name, setName] = useState('');

  // ...์ƒ๋žต
}

๋˜ํ•œ ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ƒํƒœ๊ฐ’์„ ๊ฐ์ฒดํ˜•์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์˜ setState ๋ฉ”์„œ๋“œ์™€ ๋‹จ๋ฆฌ useState๋Š” ์ด์ „ ์„ฑํƒœ๊ฐ’์„ ์ง€์šฐ๊ณ  ํ• ๋‹น๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„๊ตฌ์กฐํ™” ํ• ๋‹น์„ ํ†ตํ•ด ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•œ๋‹ค.

const Person = () => {
  const [data, setData] = useState({
    age: 0,
    name: '',
  });
}

useState ๊ตฌํ˜„ํ•˜๊ธฐ

๋‹ค์Œ์€ ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•ด ๋งŒ๋“  ๊ฐ„๋‹จํ•œ React ๋ณต์‚ฌ๋ณธ์ด๋‹ค. ์œ„์—์„œ ์‚ดํŽด๋ณธ useState ์™€ ํ•จ๊ป˜ ํ•„์š”ํ•œ ๋ช‡๊ฐ€์ง€ ๋ณ€์ˆ˜๋“ค์ด ๊ตฌํ˜„๋˜์–ด์žˆ๋‹ค. ๋ช‡๊ฐ€์ง€ ์ค‘์š”ํ•œ ๋ถ€๋ถ„๋“ค๋งŒ ์‚ดํŽด๋ณด์ž.


  • useStateํ•จ์ˆ˜ ๋‚ด๋ถ€์—๋Š” setState๋ผ๋Š” ๋‚ด์žฅํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค. setState๋Š” ๋ชจ๋“ˆ๋‚ด์— ์œ„์น˜ํ•œ hooks์™€ currentHook๋ณ€์ˆ˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
  • useStateํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ• ๋•Œ ๋งˆ๋‹ค currentHook ๋ณ€์ˆ˜์˜ ๊ฐ’์ด 1์”ฉ ์ฆ๊ฐ€ํ•œ๋‹ค. ์ด๋•Œ currentHook์˜ ๊ฐ’์„ setStateHookIndex์— ์ €์žฅํ•˜๊ณ , setState๊ฐ€ ์ด ๊ฐ’์„ ์ฐธ์กฐํ•˜๋Š” ํด๋กœ์ €๊ฐ€ ๋˜์–ด ๋งค๋ฒˆ ํ•ด๋‹น ํ›…์˜ ์œ„์น˜๋ฅผ ๊ธฐ์–ตํ•ด ์ƒํƒœ๊ฐ’์„ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค. ๋ฆฌ์•กํŠธ๋Š” ์‹ค์ œ๋กœ ํ›…์ด ์‚ฌ์šฉ๋œ ์ˆœ์„œ๋ฅผ ๋ฐฐ์—ด๋กœ ์ €์žฅํ•˜๊ณ  ์ €์žฅ๋œ ์ˆœ์„œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ›…์„ ๊ด€๋ฆฌํ•œ๋‹ค.
  • render ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ• ๋•Œ ๋งˆ๋‹ค currentHook ๋ณ€์ˆ˜์˜ ๊ฐ’์„ 0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค. renderํ•จ์ˆ˜ ๋‚ด์—์„œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‹คํ–‰๋˜๋ฉด currentHook์˜ ๊ฐ’์ด ์ปดํฌ๋„ŒํŠธ๋‚ด์—์„œ useState๋ฅผ ์‹คํ–‰ํ•œ ๋งŒํผ ๊ณ„์† ๋Š˜์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
const MyReact = (function() {
  let hooks = [];
  let currentHook = 0;
  
  return {
    render(Component) {
      const Comp = Component();
      Comp.render();
      currentHook = 0; // ๋‹ค์Œ ๋ Œ๋”๋ฅผ ์œ„ํ•ด ์ธ๋ฑ์Šค ๊ฐ’์„ ์ดˆ๊ธฐํ™”
      return Comp;
    },
    
    useState(initialState) {
      hooks[currentHook] = hooks[currentHook] || initialState;
      const setStateHookIndex = currentHook;

      // useState๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋‹น์‹œ์˜ setStateHookIndex๊ฐ’์„ ๊ธฐ์–ตํ•œ๋‹ค.
      const setState = newState => {
        hooks[setStateHookIndex] = newState;
        return hooks[setStateHookIndex];
      }

      return [hooks[currentHook++], setState];
    },
  }
})();

ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์— ์ ์šฉ

์œ„์—์„œ ๋งŒ๋“  MyReact์™€ useState ํ•จ์ˆ˜๋ฅผ Person ์ปดํฌ๋„ŒํŠธ์— ์ ์šฉํ•ด ๋ณด์•˜๋‹ค.

function Counter() {
  const [count, setCount] = MyReact.useState(0);
  const [text, setText] = MyReact.useState('');

  return {
    click: () => setCount(count + 1),
    type: txt => setText(txt),
    // DOM์„ ๋žœ๋”๋ง ํ•˜๋Š” ๋Œ€์‹  ์ฝ˜์†”์— ์ƒํƒœ๊ฐ’์„ ๋ณด์—ฌ์ฃผ๊ธฐ๋กœ ํ•œ๋‹ค.
    render: () => console.log('render:', { count, text }),
  };
}

var App = MyReact.render(Counter); // ์ดˆ๊ธฐ๊ฐ’ render: {count: 0, text: ""}
App.click();
App.type('ํ…์ŠคํŠธ์ž…๋ ฅ');
App = MyReact.render(Counter); // render: {count: 1, text: "ํ…์ŠคํŠธ์ž…๋ ฅ"}
App.click();
App = MyReact.render(Counter); // render: {count: 2, text: "ํ…์ŠคํŠธ์ž…๋ ฅ"}

useEffect

useEffect ํ›…์„ ์‚ฌ์šฉํ•˜๋ฉด ์ƒํƒœ๊ฐ’์˜ ๋ณ€ํ™”์— ๋”ฐ๋ฅธ ๋ถ€์ˆ˜ํšจ๊ณผ๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•ด ์ปดํฌ๋„ŒํŠธ์˜ ์ƒ๋ช…์ฃผ๊ธฐ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜ ์žˆ๊ณ , ๋™์‹œ์— ์ƒํƒœ๊ฐ’์— ๊ด€๋ จ๋œ ๊ธฐ๋Šฅ์„ ๋ชจ์„ ์ˆ˜ ์žˆ์–ด ์ฝ”๋“œ๊ด€๋ฆฌ๊ฐ€ ์šฉ์ดํ•ด์ง„๋‹ค.

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

  // count๊ฐ€ ์ƒํƒœ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋ฐœ์ƒ๋˜๋Š” ๋ถ€์ˆ˜ํšจ๊ณผ
  useEffect(() => {
    console.log('count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ', count);
    return () => console.log('count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ ๋ฐœ์ƒ ์ง์ „', count);
  }, [count]);
}

useEffect์˜ ์ฒซ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋“ฑ๋ก๋œ ์ฝœ๋ฐฑํ•จ์ˆ˜๋Š”(์ดํ›„ ์ฝœ๋ฐฑํ•จ์ˆ˜) ํŠน์ • ์ƒํƒœ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„๋•Œ ์ž‘๋™ํ•˜๋Š” ๋ถ€์ˆ˜ํšจ๊ณผ์ด๋‹ค. ์ฝœ๋ฐฑํ•จ์ˆ˜๋Š” ๋˜ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋ฐ˜ํ™˜๋œ ํ•จ์ˆ˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ ๋˜์—ˆ์„๋•Œ ๊ทธ๋ฆฌ๊ณ  ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๊ธฐ ์ง์ „์— ํ˜ธ์ถœ๋˜๊ณ  ์ด ํ•จ์ˆ˜๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ์ƒํƒœ๊ฐ’์€ ๋ณ€๊ฒฝ๋˜๊ธฐ ์ง์ „์˜ ๊ฐ’์ด๋‹ค.

[์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ ๋˜์—ˆ์„๋•Œ]
count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ 0

[count๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„๋•Œ]
count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ ๋ฐœ์ƒ ์ง์ „ 0 => ๋ฐ˜ํ™˜๋œ ํ•จ์ˆ˜๊ฐ€ ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๊ธฐ ์ง์ „์— ํ˜ธ์ถœ๋จ
count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ 1
count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ ๋ฐœ์ƒ ์ง์ „ 1
count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ 2

๋‘๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ๋Š” ๋ฐฐ์—ด์„ ๋ฐ›๋Š”๋ฐ, ์ด ๋ฐฐ์—ด์˜ ์š”์†Œ์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋นˆ๋ฐฐ์—ด์„ ๋„ฃ์œผ๋ฉด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ๋ ๋•Œ๋งŒ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ๋ ๋•Œ๋งŒ ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.(componentDidMount, componentWillUnmount์™€ ๊ฐ™์€ ์šฉ๋„๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค) ๋งŒ์•ฝ ์•„๋ฌด๊ฒƒ๋„ ๋„ฃ์ง€ ์•Š์œผ๋ฉด ๋ชจ๋“  ์ƒํƒœ ๋ณ€๊ฒฝ์— ๋ฐ˜์‘ํ•˜์—ฌ ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.


useEffect ํ›…์˜ ๋‘๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ์ฝœ๋ฐฑํ•จ์ˆ˜ ํ˜ธ์ถœ ๊ด€๊ณ„ ์ •๋ฆฌ

  • ๋นˆ ๋ฐฐ์—ด([]) : ๋งˆ์šดํŠธ/์–ธ๋งˆ์šดํŠธ์‹œ ์ฝœ๋ฐฑ ํ˜ธ์ถœ
  • ์•„๋ฌด๊ฒƒ๋„ ๋„ฃ์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ : ๋ชจ๋“  ์ƒํƒœ ๋ณ€๊ฒฝ์— ๋Œ€ํ•˜์—ฌ ์ฝœ๋ฐฑ ํ˜ธ์ถœ
  • ํŠน์ • ์ƒํƒœ๋ฅผ ์š”์†Œ๋กœ ๋„ฃ์€ ๋ฐฐ์—ด : ํ•ด๋‹น ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๊ฒฝ์šฐ ์ฝœ๋ฐฑ ํ˜ธ์ถœ

useEffect ๊ตฌํ˜„ํ•˜๊ธฐ

useEffect์€ ๋‘๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— callback ๊ณผ dependencies๋ฅผ ๋ฐ›๋Š”๋‹ค. (์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์— ๋Œ€ํ•ด์„œ๋Š” ๊ตฌํ˜„ํ•˜์ง€ ์•Š๋Š”๋‹ค)

const MyReact = (function() {
  let hooks = [];
  let currentHook = 0;
  
  return {
    render(Component) {
      const Comp = Component();
      Comp.render();
      currentHook = 0; // ๋‹ค์Œ ๋ Œ๋”๋ฅผ ์œ„ํ•ด ์ธ๋ฑ์Šค ๊ฐ’์„ ์ดˆ๊ธฐํ™”
      return Comp;
    },
    useEffect(callback, dependencies) {      const hasNoDependencies = !dependencies;      const states = hooks[currentHook]; // type: array | undefined      const hasChangedStates = states ?         !dependencies.every((el, i) => el === states[i]) : true;      if (hasNoDependencies || hasChangedStates) {        callback(); // ์ƒํƒœ๊ฐ’์ด ์—†๊ฑฐ๋‚˜ ์˜์กดํ•˜๋Š” ๊ฐ’์ด ์—†์œผ๋ฉด ๋ฌด์กฐ๊ฑด ํ˜ธ์ถœ๋œ๋‹ค.        hooks[currentHook] = dependencies;      }      currentHook++; // ์ด๋ฒˆ ํ›…์— ๋Œ€ํ•œ ์ž‘์—…์ด ๋๋‚ฌ์Œ.    },    useState(initialState) {
      hooks[currentHook] = hooks[currentHook] || initialState;
      const setStateHookIndex = currentHook;

      // useState๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋‹น์‹œ์˜ setStateHookIndex๊ฐ’์„ ๊ธฐ์–ตํ•œ๋‹ค.
      const setState = newState => {
        hooks[setStateHookIndex] = newState;
        return hooks[setStateHookIndex];
      }

      return [hooks[currentHook++], setState];
    },
  }
})();

์•ž์„œ ๋งŒ๋“  Person ์ปดํฌ๋„ŒํŠธ์— useEffect ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•ด ๋ณด์•˜๋‹ค.

const { useState, useEffect, render } = MyReact;

function Counter() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  useEffect(    console.log('count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ', count);  ,[count]);
  return {
    click: () => setCount(count + 1),
    type: txt => setText(txt),
    render: () => console.log('render:', { count, text }),
  };
}

var App = render(Counter); 
// count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ 0 => ๋งˆ์šดํŠธ์‹œ ํ˜ธ์ถœ
// render: {count: 0, text: ""}
App.click();
App = render(Counter);
// count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ 1
// render: {count: 1, text: ""}
App.type('ํ…์ŠคํŠธ์ž…๋ ฅ');
App = render(Counter);
// text ์ƒํƒœ๊ฐ’ ๋ณ€๊ฒฝ์— ๋Œ€ํ•ด์„œ๋Š” ๋ถ€์ˆ˜ํšจ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ.
// render: {count: 1, text: "ํ…์ŠคํŠธ์ž…๋ ฅ"} 
App.click();
App = render(Counter);
// count์˜ ๋ถ€์ˆ˜ํšจ๊ณผ 2
// render: {count: 2, text: "ํ…์ŠคํŠธ์ž…๋ ฅ"}

์ •๋ฆฌ

  • ํ›…์€ ํด๋กœ์ €๋กœ ๊ตฌํ˜„๋˜์—ˆ๋‹ค.
  • ํ›…์€ ํ•จ์ˆ˜๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ์ธ๋ฑ์Šค ๋ณ€์ˆ˜(์—ญ์‹œ ํด๋กœ์ €)๋ฅผ ํ†ตํ•ด ๋ฐฐ์—ด์— ๊ฐ’์„ ํ• ๋‹นํ•˜๊ณ  ๊ฐ€์ ธ์˜ค๋Š”๊ฒƒ ๋ฟ์ด๋‹ค.(Not Magic, just Arrays)

์ฐธ๊ณ