๋ณธ๋ฌธ์œผ๋กœ ๋ฐ”๋กœ๊ฐ€๊ธฐ

[React] 8. Hooks

category Web/React 2023. 11. 6. 07:04

 

  • ๋ฆฌ์•กํŠธ 16.8์—์„œ ๋“ฑ์žฅ
  • Hook์„ ์‚ฌ์šฉํ•˜๋ฉด, ํด๋ž˜์Šค์ปดํฌ๋„ŒํŠธ์˜ ๊ธฐ๋Šฅ์„ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ด์ค€๋‹ค!

Hook

  • ๊ฐˆ๊ณ ๋ฆฌ
  • ์›๋ž˜ ์กด์žฌํ•˜๋Š” ๊ธฐ๋Šฅ์— ๊ฐˆ๊ณ ๋ฆฌ๋ฅผ ๊ฑธ์–ด ์›ํ•˜๋Š” ์‹œ์ ์— ์ •ํ•ด์ค€ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ํ•จ.
  • use~ ๋กœ ์‹œ์ž‘ํ•จ.

 

๋Œ€ํ‘œ์ ์ธ Hook (use ์–ด์ฉŒ๊ตฌ)

useState() ํ›…

  • state๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ Hook
  • ํ•จ์ˆ˜์ปดํฌ๋„ŒํŠธ์—์„œ ํด๋ž˜์Šค์ปดํฌ๋„ŒํŠธ์ฒ˜๋Ÿผ state๋ฅผ ์“ฐ๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•จ.
    • ex) ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๋ Œ๋”๋ง์ด ๋˜์–ด์•ผ ํ•œ๋‹ค. useState๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๋ Œ๋”๋ง์ด ๋˜๋„๋ก ํ•จ.
  • state๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๋ Œ๋”๋ง๋˜๋„๋กํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.
  • ์‚ฌ์šฉ๋ฒ•
const [๋ณ€์ˆ˜๋ช…, setํ•จ์ˆ˜๋ช…] = useState(state์˜ ์ดˆ๊ธฐ๊ฐ’);
* ๋ณ€์ˆ˜ ๊ฐ๊ฐ์— ๋Œ€ํ•ด setํ•จ์ˆ˜๊ฐ€ ๋”ฐ๋กœ ์กด์žฌํ•œ๋‹ค.

useEffect() ํ›…

  • side effect๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ Hook
    • side effect? ⇒ ์›๋ž˜์˜๋ฏธ๋Š” ๋ถ€์ž‘์šฉ์ด๋‚˜, ๋ฆฌ์•กํŠธ์—์„œ๋Š” “ํšจ๊ณผ”, “์˜ํ–ฅ”์„ ์˜๋ฏธํ•œ๋‹ค.
      • ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ Œ๋”๋ง์ด ๋๋‚œ ์ดํ›„์— ์‹คํ–‰๋˜๋Š” ์ž‘์—…๋“ค.
  • componentDidMount, componentDidUpdate, componentWillUnmount ์™€ ๋™์ผํ•œ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋œ๋‹ค.
  • ์‚ฌ์šฉ๋ฒ•
    • useEffect() ํ›…์˜ return๋ถ€๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ unmount๋  ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.
    • ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์— ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์˜์กด์„ฑ๋ฐฐ์—ด ์•ˆ์˜ ๊ฐ’์ด ์—…๋ฐ์ดํŠธ๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋˜๋‚˜,
  • ๋งˆ์ง€๋ง‰ ์˜์กด์„ฑ ๋ฐฐ์—ด ์ƒ๋žต ์‹œ์—๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—…๋ฐ์ดํŠธ๋  ๋•Œ๋งˆ๋‹ค ์‹คํ–‰๋œ๋‹ค.

useMemo() ํ›…

  • Memoized value๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” ํ›…

useCallback() ํ›…

  • ์˜์กด์„ฑ๋ฐฐ์—ด ๋‚ด ๋ณ€์ˆ˜ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ๋ณ€๊ฒฝ๋˜๋ฉด ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋จ.
  • ์˜์กด์„ฑ๋ฐฐ์—ด์ด ๋น„์—ˆ์„ ๊ฒฝ์šฐ, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ ๋งˆ์šดํŠธ๋˜๋Š” ์‹œ์ ์—๋งŒ ํ•œ ๋ฒˆ ์‹คํ–‰๋˜๋ฉฐ ์ดํ›„์—๋Š” ์ •์˜๋˜์ง€ ์•Š์Œ. ⇒ ๋ถˆํ•„์š”ํ•œ ์žฌ๋ Œ๋”๋ง์ด ์ผ์–ด๋‚˜์ง€ ์•Š์Œ.

useRef() ํ›…

  • reference : ํŠน์ • ์ปดํฌ๋„ŒํŠธ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด
  • ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•จ.

 

Hook์˜ ๊ทœ์น™

  1. ํ›…์€ ๋ฌด์กฐ๊ฑด ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์—์„œ๋งŒ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
    • ๋ฐ˜๋ณต๋ฌธ, ์กฐ๊ฑด๋ฌธ์—์„œ ํ˜ธ์ถœํ•˜๋ฉด ์•ˆ๋œ๋‹ค. ์ปดํฌ๋„ŒํŠธ ์•ˆ์— ์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ์—์„œ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•จ.
    • ์กฐ๊ฑด๋ฌธ์— ๋”ฐ๋ผ ์‹คํ–‰๋˜๋Š” ํ›…์ด ๋‹ฌ๋ผ์ง€๋ฉด ์•ˆ๋œ๋‹ค.
  2. ๋ฆฌ์•กํŠธ ํ•จ์ˆ˜ ์ปดํฌ๋„ŒํŠธ์—์„œ๋งŒ ํ›…์„ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
eslint-plugin-react-hooks
์ •์ ์ฝ”๋“œ๋ถ„์„๋„๊ตฌ
๋ฆฌ์•กํŠธ๊ฐ€ ํ›…์˜ ๊ทœ์น™์„ ๋”ฐ๋ฅด๋Š”์ง€ ์ฒดํฌํ•ด์ฃผ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ.

Custom Hook ๋งŒ๋“ค๊ธฐ

  • ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋กœ์ง์„ ํ›…์œผ๋กœ ๋งŒ๋“ค์–ด ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•จ.
  • ์ค‘๋ณต๋˜๋Š” ๋กœ์ง์„ ์ปค์Šคํ…€ํ›…์œผ๋กœ ์ถ”์ถœํ•œ๋‹ค.
  • ์ปค์Šคํ…€ํ›…์˜ ์ด๋ฆ„์€ ๊ผญ use๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค!
  • ์ปค์Šคํ…€ํ›…์€ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ ๋ชจ๋“  state, effects๋Š” ์ „๋ถ€ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๋‹ค.
  • ๊ฐ๊ฐ์˜ ์ปค์Šคํ…€ํ›… ํ˜ธ์ถœ์— ๋Œ€ํ•ด ๋ถ„๋ฆฌ๋œ state๋ฅผ ์–ป๊ฒŒ ๋œ๋‹ค.

Hook ์‚ฌ์šฉํ•˜๊ธฐ

useCounter.jsx

import React, {useState} from "react";

function useCounter(initialValue) {
  const [count, setCount] = useState(initialValue);

  const increaseCount = () => setCount((count) => count + 1);
  const decreaseCount = () => setCount((count) => Math.max(count - 1, 0));

  return [count, increaseCount, decreaseCount];
}

export default useCounter;

Accomodate.jsx

import React, {useState, useEffect} from "react";
import useCounter from "./useCounter";

const MAX_CAPACITY = 10;

function Accomodate(props) {
  const [isFull, setIsFull] = useState(false);
  const [count, increaseCount, decreaseCount] = useCounter(0);

  // ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—…๋ฐ์ดํŠธ๋  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ
  useEffect(() => {
    console.log("==================");
    console.log("useEffect() is called.");
    console.log(`isFull: ${isFull}`);
  });

  // cout ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ
  useEffect(() => {
    setIsFull(count >= MAX_CAPACITY);
    console.log(`Current count value: ${count}`);
  }, [count]);

  return (
    <div style={{padding: 16}}>
      <p>{`์ด ${count}๋ช… ์ˆ˜์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.`}</p>
      <button onClick={increaseCount} disabled={isFull}>
        ์ž…์žฅ
      </button>
      <button onClick={decreaseCount}>ํ‡ด์žฅ</button>

      {isFull && <p style={{color: "red"}}>์ •์›์ด ๊ฐ€๋“ ์ฐผ์Šต๋‹ˆ๋‹ค.</p>}
    </div>
  );
}

export default Accomodate;

index.js

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
//import App from "./App";
import reportWebVitals from "./reportWebVitals";

//import Library from "./chapter_03/Library";
// import Clock from "./chapter_04/Clock";
// import CommentList from "./chapter_05/CommentList";
// import NotificationList from "./chapter_06/NotificationList";
import Accomodate from "./chapter_07/Accomodate";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Accomodate />
  </React.StrictMode>
);

reportWebVitals();

 

๊ฒฐ๊ณผ

'Web > React' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[React] 7. State and Lifecycle  (0) 2023.11.05
[React] 6. Components and Props  (0) 2023.11.05
[React] Error: react_dom_client__WEBPACK_IMPORTED_MODULE_1__.render is not a function  (0) 2023.11.05
[React] 6. Rendering Elements  (0) 2023.11.05
[React] Error: Already included file name  (0) 2023.11.05