React : useEffect

<angeLog/>ยท2024๋…„ 2์›” 21์ผ

REACT

๋ชฉ๋ก ๋ณด๊ธฐ
8/25
post-thumbnail

๐Ÿ’ก๋…ธ๋งˆ๋“œ์ฝ”๋” ๋‹ˆ๊ผฌ์Œค์˜ ๊ฐ•์˜๋ฅผ ๋ณด๋ฉฐ ๊ณต๋ถ€ํ•˜๋Š” ์‹œ๋ฆฌ์ฆˆ์ž…๋‹ˆ๋‹ค.

state๊ฐ€ ๋ณ€ํ•˜๋Š” Button์„ ์ผ๋‹จ ๋งŒ๋“ค์—ˆ๋‹ค.

import { useState } from 'react';
function App() {
  const [counter, setValue] = useState(0);
  const onClick = () => setValue((prev) => prev + 1);
  console.log('I RUN ALL THE TIME');
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={onClick}>ํด๋ฆญํด๋ฆญ</button>
    </div>
  );
}
export default App;

useState์˜ ์‚ฌ์šฉ๋ฌธ๋ฒ•์ด ์ข€ ๋‹ค๋ฅด์ง€?
react๋ฅผ installํ•œ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— React.useState(init)๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฐ”๋กœ useState(init)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ณธ๋ก ์œผ๋กœ ๋„˜์–ด๊ฐ€์„œ ์ฝ˜์†”์„ ํ™•์ธํ•ด๋ณด๋ฉด...?
state๊ฐ€ ๋ณ€ํ•  ๋•Œ ๋งˆ๋‹ค ์ฝ˜์†”์ด ์ฐํžˆ๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋Ÿฐ๋ฐ ๋งŒ์•ฝ์— ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
์˜ˆ๋ฅผ ๋“ค๋ฉด api๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ, ์ด ๋ฐฉ์‹๋Œ€๋กœ๋ผ๋ฉด state๊ฐ€ ๋ณ€ํ•  ๋•Œ๋งˆ๋‹ค api๋ฅผ ๊ณ„์† ํ˜ธ์ถœํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋Ÿด ํ•„์š”๊ฐ€ ์žˆ์„๊นŒ? (์žˆ์„ ์ˆ˜๋„ ์žˆ๊ฒ ์ง€๋งŒ!)

useEffect

useEffect
useState์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ React Hook์˜ ์ผ์ข…์ด๋‹ค. ๋‘๊ฐœ์˜ argument(์ „๋‹ฌ์ธ์ž)๋ฅผ ๊ฐ€์ง„๋‹ค.

useEfect๋ฅผ importํ•˜๊ณ  ์ฒซ๋ฒˆ์งธ argument์—๋Š” ์‹คํ–‰ํ•˜๊ณ ์ž ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ, ๋‘๋ฒˆ์งธ argument๋Š” [๋Œ€๊ด„ํ˜ธ]๋กœ ๋‚จ๊ฒจ๋‘” ์ฑ„๋กœ ์‹คํ–‰ํ•ด๋ณด์ž.

import { useState, useEffect } from 'react';
function App() {
  const [counter, setValue] = useState(0);
  const onClick = () => setValue((prev) => prev + 1);
  console.log('I RUN ALL THE TIME');
  const iRunOnlyOnce = () => {
    console.log('I RUN ONLY ONCE');
  };
  useEffect(iRunOnlyOnce, []);
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={onClick}>ํด๋ฆญํด๋ฆญ</button>
    </div>
  );
}
export default App;

๊ทธ๋Ÿฐ๋ฐ ๋ถˆํ˜„๋“ฏ ๋ˆˆ์— ๋ˆ ์ € ์• ๋“ค์€ ๋Œ€์ฒด ์™œ ์ €๋Ÿฌ๋Š”๊ฑธ๊นŒ?
๋‹ต์€ index.js์— ์žˆ๋‹ค.
root.render ํ•จ์ˆ˜์— <React.StrictMode>์— ์žˆ๋‹ค.
๋ฆฌ์—‘ํŠธ ๊ณต์‹๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด StrictMode๋Š” ๋ฒ„๊ทธ๋ฅผ ์ฐพ๊ธฐ์œ„ํ•ด Re-render๋ฅผ ํ•œ๋‹ค๊ณ  ์ ํ˜€์žˆ๋‹ค.
๋‚˜๋Š” ์—„๊ฒฉํ•œ ๋ชจ๋“œ๊ฐ€ ํ•„์š”์—†๋Š” ์ƒํƒœ์ด๋ฏ€๋กœ ๊ณผ๊ฐํžˆ ์ง€์› ๋‹ค.
ํ•œ ๋ฒˆ์”ฉ๋งŒ render ๋˜๋Š” ๊ฒƒ ํ™•์ธ!

๋‹ค์‹œ ๋ณธ๋ก ์œผ๋กœ ๋Œ์•„์™€์„œ
useEffect์‚ฌ์šฉํ•ด ๋ดค์œผ๋‹ˆ๊นŒ ์ € ์•„์ด๊ฐ€ ์–ด๋–ค ๊ธฐ๋Šฅ์„ ํ•˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด์ž.

์˜ค, useEffect๋ฅผ ์‚ฌ์šฉํ•œ ํ•จ์ˆ˜๋Š” ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋œ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด useEffect์˜ ๋‘๋ฒˆ์งธ argument๋Š” ์–ด๋–ค ๊ธฐ๋Šฅ์„ ๊ฐ€์กŒ์„๊นŒ?

Magic of useEffect

useEffect๋Š” state์˜ ๋ณ€ํ™”์— ๋”ฐ๋ผ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ๋•๋Š” reactHook์ด๋ผ๊ณ  ์ƒ๊ฐ๋œ๋‹ค.
์•„๊นŒ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด useEffect๋Š” ๋‘๊ฐœ์˜ ์ „๋‹ฌ์ธ์ž๋ฅผ ๊ฐ–๋Š”๋ฐ ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋Š” ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜. ๋‘๋ฒˆ์งธ ์ธ์ž๋Š” ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ธฐ์ค€์ . ์ฆ‰, ์˜์กด๊ฐ’ ์ด๋‹ค.

  useEffect(() => {
    console.log('I RUN ONLY ONCE');
  }, []);

์œ„ ์ฝ”๋“œ๋ฅผ ์˜ˆ์‹œ๋กœ ๋“ค์ž๋ฉด, ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋Š” console์ด๊ณ , ๋‘ ๋ฒˆ์งธ ์ธ์ž(์˜์กด๊ฐ’)๋Š” ๋นˆ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฝ˜์†”์— ๋‹จ ํ•œ ๋ฒˆ๋งŒ ์ถœ๋ ฅ์ด ๋œ๋‹ค. ์˜์กด๊ฐ’์— state๋ฅผ ๋„ฃ์œผ๋ฉด ํ•ด๋‹น state์˜ ๋ณ€ํ™”์— ๋”ฐ๋ผ console์ด ์ฐํžˆ๊ฒŒ ๋˜๋Š” ๋˜๋Š” ์•„์ฃผ ๋งˆ๋ฒ•๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

import { useState, useEffect } from 'react';
function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState('');
  const onClick = () => setValue((prev) => prev + 1);
  const onChange = (e) => setKeyword(e.target.value);
  
  //์ œํ•œ ์‚ฌํ•ญ์ด ์—†์œผ๋ฏ€๋กœ ๊ทธ ์–ด๋–ค state๊ฐ€ ๋ณ€ํ•˜๋“  ์˜์›ํžˆ ์ถœ๋ ฅ๋œ๋‹ค.
  console.log('I RUN ALL THE TIME');
  
  useEffect(() => {
    //์˜์กด๊ฐ’์ด ๋นˆ๊ฐ’์ด๋ฏ€๋กœ ์žฌ์‹คํ–‰ ํฌ์ธํŠธ๊ฐ€ ์—†์–ด์„œ ๋‹จ ํ•œ ๋ฒˆ๋งŒ render.
    console.log('I RUN ONLY ONCE');
  }, []);
  
  useEffect(() => {
    //์˜์กด๊ฐ’ keyword๊ฐ€ ๋ณ€ํ•  ๋•Œ๋งˆ๋‹ค render.
    console.log('I RUN WHEN "KEYWORD" CHAGE');
  }, [keyword]);
  
  useEffect(() => {
    //์˜์กด๊ฐ’ counter ๋ณ€ํ•  ๋•Œ๋งˆ๋‹ค render.
    console.log('I RUN WHEN "COUNTER" CHAGE');
  }, [counter]);
  
  useEffect(() => {
    // ์˜์กด๊ฐ’์€ ๋ฐฐ์—ด๋กœ ๋ฌถ์„ ์ˆ˜๋„ ์žˆ๋‹ค.
    console.log('I RUN WHEN "KEYWORD & COUNTER" CHAGE');
  }, [keyword, counter]);
  return (
    <div>
      <input
        type={keyword}
        placeholder="searchHere"
        onChange={onChange}
      />
      <h1>{counter}</h1>
      <button onClick={onClick}>ํด๋ฆญํด๋ฆญ</button>
    </div>
  );
}
export default App;

Clean-up Function

Clean-up Function
๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ , ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์œ ์ง€ํ•˜๋ฉฐ, ํ•„์š” ์—†์–ด์ง„ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ œ๊ฑฐํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ํ•จ์ˆ˜

//๋ฌธ๋ฒ•
useEffect(() => {
    (์ดํŽ™ํŠธ ํ•จ์ˆ˜)
    return {
        (ํด๋ฆฐ์—… ํ•จ์ˆ˜)
    };
}, [์˜์กด๊ฐ’]);

importํ•˜๋Š” component๊ฐ€ ํ•œ ๊ฐœ๋ผ๋ฉด ํฌ๊ฒŒ ๋ฌธ์ œ๊ฐ€ ์—†๊ฒ ์ง€๋งŒ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฌ๋Ÿฌ๋ฒˆ ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ ํ™”๋ฉด์—์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ง€์› ์„ ๋•Œ(Destroy) useEffect๋กœ ์„ค์ •๋œ sideEffect๊ฐ€ ์ •๋ฆฌ๋˜์ง€ ์•Š์•„ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๊ฒƒ์„ ๋ฏธ์—ฐ์— ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด clean-up function์ด๋‹ค.

//์‘์šฉ1
function Hello() {
  useEffect(() => {
    // ์ดํŽ™ํŠธ ํ•จ์ˆ˜
    console.log('CREATE');
    // ํด๋ฆฐ์—… ํ•จ์ˆ˜
    return () => console.log('DESTROY');
  }, []);
  return <h1>HELLO</h1>;
}
//์‘์šฉ2
function Hello() {
  const hiFunc = () => {
    console.log('CREATE');
    
    //ํด๋ฆฐ์—… ํ•จ์ˆ˜
    return byeFunf;
  };
  const byeFunf = () => {
    console.log('DESTROY');
  };
  useEffect(hiFunc, []);
  return <h1>HELLO</h1>;
}

๋‘๊ฐœ ๋ชจ๋‘ ๋™์ผํ•œ ๋™์ž‘์„ ํ•œ๋‹ค.

๐Ÿ‘‰๐ŸปReact - useEffect ํ›… (์ดํŽ™ํŠธ ํ•จ์ˆ˜, ํด๋ฆฐ์—… ํ•จ์ˆ˜)
๐Ÿ‘‰๐ŸปuseEffect์˜ ํด๋ฆฐ์—…์˜ ํ•„์š”์„ฑ

profile
์ผ๋‹จ ํ•ด๋ณผ๊ฒŒ์š”!โœ๐Ÿป

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