[노마드코더] React JS Ch.3~6

김서윤·2024년 1월 22일
post-thumbnail

#3 STATE

3.0 Understanding State

State → (값이 바뀔) 데이터가 저장되는 곳

  • index.html → not good
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        let counter = 0;
        function countUp() {
          counter = counter + 1;
          render();
        }
        function render() {
          ReactDOM.render(<Container />, root);
        }
        const Container = () => (
          <div>
            <h3>Total clicks: {counter}</h3>
            <button onClick={countUp}>Click me</button>
          </div>
        );
        render();
      </script>
    </html>

Total clicks: {counter} : {counter}로 변수를 가져올 수 있음

→ 초기의 렌더링만으로 끝내는 것이 아니라 리렌더링을 해줘야 변하는 UI 렌더링 가능

→ 현재 코드는 계속해서 모든 부분을 render 해주기 때문에 좋은 방식 X

→ vanillaJS와 달리 React.js는 UI에서 바뀐 부분만 업데이트 가능
(ex. button 업데이트 X, click 숫자만 업데이트)

3.1 setState part One

  • index.html → Best way (not final)
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function App() {
          const [counter, modifier] = React.useState(0);
          return (
            <div>
              <h3>Total clicks: {counter}</h3>
              <button>Click me</button>
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

→ 함수를 계속 불러줄 필요 없이 데이터를 보관하고 자동으로 리렌더링하는 최고의 방법

const data = React.useState(0); : [초기값(0), 함수] 2개가 담겨있는 배열, 함수의 역할

3.2 setState part Two

  • index.html → Best way (final)
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function App() {
          const [counter, setCounter] = React.useState(0);
          const onClick = () => {
            setCounter(counter + 1);
          };
          return (
            <div>
              <h3>Total clicks: {counter}</h3>
              <button onClick={onClick}>Click me</button>
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

React.useState : counter데이터를 숫자형 데이터로 전달, 데이터 값 바꿀 함수 같이 전달
(+ 함수로 바꾼 값 리렌더링)

3.3 Recap

위와 동일

3.4 State Functions

  • index.html
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function App() {
          const [counter, setCounter] = React.useState(0);
          const onClick = () => {
            // setCounter(counter + 1);
            setCounter((current) => current + 1);
          };
          return (
            <div>
              <h3>Total clicks: {counter}</h3>
              <button onClick={onClick}>Click me</button>
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

→ 1. setCounter(10); : 새 값으로 변경 (하지만 더 이상의 업데이트 X)

→ 2. setCounter(counter + 1); : 이전 값을 이용해서 현재 값을 계산 (계속 업데이트 O)

→ 3. setCounter((current) => current + 1); : Best Way / 확실히 현재 값 보장 (안전)

3.5 Inputs and State

  • index.html → Super Converter 中 Minutes ↔ Hours (1)
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function App() {
          const [minutes, setMinutes] = React.useState(0);
          const onChange = (event) => {
            setMinutes(event.target.value);
          };
          return (
            <div>
              <h1>Super Converter</h1>
              <label htmlFor="minutes">Minutes</label>
              <input value={minutes} id="minutes" placeholder="Minutes" type="number" onChange={onChange} />
              <h4>You want to convert {minutes}</h4>
              <label htmlFor="hours">Hours</label>
              <input id="hours" placeholder="Hours" type="number" />
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

NOT class YES className / NOT for YES htmlFor

→ 기본 input은 uncontrolled : value 값을 통제할 수 없음 → state 생성 필요

event.target.value : event를 사용하여 input 값 중 target의 value값 사용

3.6 State Practice part One

  • index.html → Super Converter 中 Minutes ↔ Hours (2)
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function App() {
          const [minutes, setMinutes] = React.useState(0);
          const onChange = (event) => {
            setMinutes(event.target.value);
          };
          const reset = () => setMinutes(0);
    
          return (
            <div>
              <h1>Super Converter</h1>
              <div>
                <label htmlFor="minutes">Minutes</label>
                <input value={minutes} id="minutes" placeholder="Minutes" type="number" onChange={onChange} />
              </div>
    
              <div>
                <label htmlFor="hours">Hours</label>
                <input value={Math.round(minutes / 60)} id="hours" placeholder="Hours" type="number" disabled />
              </div>
    
              <button onClick={reset}>Reset</button>
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

Math.round() : 값 반올림해주는 함수

const reset = () => setMinutes(0); : 0으로 초기화

→ Hours : onChange 리스너가 없기 때문에 input 값 변경 불가
disabled 로 인해 입력 불가

3.7 State Practice part Two

  • index.html → Super Converter 中 Minutes ↔ Hours (3)
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function App() {
          const [amount, setAmount] = React.useState(0);
          const [flipped, setFlipped] = React.useState(false);
          const onChange = (event) => {
            setAmount(event.target.value);
          };
          const reset = () => setAmount(0);
          const onFlip = () => {
            reset();
            setFlipped((current) => !current);
          };
    
          return (
            <div>
              <h1>Super Converter</h1>
              <div>
                <label htmlFor="minutes">Minutes</label>
                <input value={flipped ? amount * 60 : amount} id="minutes" placeholder="Minutes" type="number" onChange={onChange} disabled={flipped} />
              </div>
    
              <div>
                <label htmlFor="hours">Hours</label>
                <input value={flipped ? amount : Math.round(amount / 60)} id="hours" placeholder="Hours" type="number" onChange={onChange} disabled={!flipped} />
              </div>
    
              <button onClick={reset}>Reset</button>
              <button onClick={onFlip}>Flip</button>
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

filp click : minutes 입력 hours 입력 불가 ↔ minutes 입력 불가 hours 입력

disabled={flipped === true}/disabled={!flipped} : disabled를 통해 flipped props 전달

3.8 Recap

  • index.html → Super Converter 中 Minutes ↔ Hours (4)
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function App() {
          const [amount, setAmount] = React.useState(0);
          const [inverted, setInverted] = React.useState(false);
          const onChange = (event) => {
            setAmount(event.target.value);
          };
          const reset = () => setAmount(0);
          const onInvert = () => {
            reset();
            setInverted((current) => !current);
          };
    
          return (
            <div>
              <h1>Super Converter</h1>
              <div>
                <label htmlFor="minutes">Minutes</label>
                <input value={inverted ? amount * 60 : amount} id="minutes" placeholder="Minutes" type="number" onChange={onChange} disabled={inverted} />
              </div>
    
              <div>
                <label htmlFor="hours">Hours</label>
                <input value={inverted ? amount : Math.round(amount / 60)} id="hours" placeholder="Hours" type="number" onChange={onChange} disabled={!inverted} />
              </div>
    
              <button onClick={reset}>Reset</button>
              <button onClick={onInvert}>{inverted ? "Turn back" : "Invert"}</button>
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

→ flipped를 inverted로 변경 및 버튼 {inverted ? "Turn back" : "Invert"} 추가

3.9 Final Practice and Recap

  • index.html → Super Converter 中 Minutes ↔ Hours + Km ↔ Miles
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function MinutesToHours() {
          const [amount, setAmount] = React.useState(0);
          const [inverted, setInverted] = React.useState(false);
          const onChange = (event) => {
            setAmount(event.target.value);
          };
          const reset = () => setAmount(0);
          const onInvert = () => {
            reset();
            setInverted((current) => !current);
          };
    
          return (
            <div>
              <div>
                <label htmlFor="minutes">Minutes</label>
                <input value={inverted ? amount * 60 : amount} id="minutes" placeholder="Minutes" type="number" onChange={onChange} disabled={inverted} />
              </div>
    
              <div>
                <label htmlFor="hours">Hours</label>
                <input value={inverted ? amount : Math.round(amount / 60)} id="hours" placeholder="Hours" type="number" onChange={onChange} disabled={!inverted} />
              </div>
    
              <button onClick={reset}>Reset</button>
              <button onClick={onInvert}>{inverted ? "Turn back" : "Invert"}</button>
            </div>
          );
        }
        function KmToMiles() {
          return <h3>KM 2 M</h3>;
        }
        function App() {
          const [index, setIndex] = React.useState("xx");
          const onSelect = (event) => {
            setIndex(event.target.value);
          };
    
          return (
            <div>
              <h1>Super Converter</h1>
              <select value={index} onChange={onSelect}>
                <option value="xx">Select your units</option>
                <option value="0">Minutes & Hours</option>
                <option value="1">Km & Miles</option>
              </select>
              <hr />
              {index === "xx" ? "Please select your units" : null}
              {index === "0" ? <MinutesToHours /> : null}
              {index === "1" ? <KmToMiles /> : null}
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

→ select, value를 활용하여 메뉴바에서 선택하는 것으로 컴포넌트 불러오기

const [index, setIndex] = React.useState();
: useState에 아무 값도 지정해주지 않았기 때문에 처음에는 어느 화면도 X

#4 PROPS

4.0 Props

  • index.html → 버튼 속 text만 변경해서 같은 컴포넌트 사용 中 using props.banana
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function Btn(props) {
          return (
            <button
              style={{
                backgroundColor: "tomato",
                color: "white",
                padding: "10px 20px",
                border: 0,
                borderRadius: 10,
              }}
            >
              {props.banana}
            </button>
          );
        }
    
        function App() {
          return (
            <div>
              <Btn banana="Save Changes" />
              <Btn banana="Continue" />
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

컴포넌트 : 어떤 JSX를 반환하는 함수

props : 버튼으로부터 전달받는 properties / 인자

Btn({banana:"Save Changes"}) = <Btn banana="Save Changes" />

→ 현재 이 코드에서 props는 버튼이 전달 받는 유일한, 첫번째 인자 → 값은 모두 가져옴

  • index.html → using {text, big}
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function Btn({ text, big }) {
          return (
            <button
              style={{
                backgroundColor: "tomato",
                color: "white",
                padding: "10px 20px",
                border: 0,
                borderRadius: 10,
                fontSize: big ? 18 : 16,
              }}
            >
              {text}
            </button>
          );
        }
    
        function App() {
          return (
            <div>
              <Btn text="Save Changes" big={true} />
              <Btn text="Continue" big={false} />
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

→ props는 오브젝트이기 때문에 property를 오브젝트로부터 꺼내는 shortcut 사용

4.1 Memo

  • index.html → (+) function
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function Btn({ text, changeValue }) {
          return (
            <button
              onClick={changeValue}
              style={{
                backgroundColor: "tomato",
                color: "white",
                padding: "10px 20px",
                border: 0,
                borderRadius: 10,
              }}
            >
              {text}
            </button>
          );
        }
        const MemorizedBtn = React.memo(Btn);
    
        function App() {
          const [value, setValue] = React.useState("Save Changes");
          const changeValue = () => setValue("Revert Changes");
    
          return (
            <div>
              <MemorizedBtn text={value} changeValue={changeValue} />
              <MemorizedBtn text="Continue" />
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

→ props에 넣을 수 있는 것 : string, boolean, function 등

→ props는 일일이 추가해줘야 사용 가능

<Btn text="{value}" onClick={changeValue} /> : onClick은 이벤트리스너 X 하나의 props
이해를 위해 changeValue={changeValue}로 작성

React Memo : props가 변경되지 않을 때 컴포넌트를 리렌더링 하지 않고 싶을 때 사용

const MemorizedBtn = React.memo(Btn); : Btn을 Memo하여 변경된 것만 리렌더링

4.2 Prop Types

  • index.html → using Prop Types
    <!DOCTYPE html>
    <html>
      <body>
        <div id="root"></div>
      </body>
      <script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
      <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
      <script src="https://unpkg.com/prop-types@15.7.2/prop-types.js"></script>
      <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
      <script type="text/babel">
        const root = document.getElementById("root");
        function Btn({ text, fontSize = 16 }) {
          return (
            <button
              style={{
                backgroundColor: "tomato",
                color: "white",
                padding: "10px 20px",
                border: 0,
                borderRadius: 10,
                fontSize,
              }}
            >
              {text}
            </button>
          );
        }
        Btn.propTypes = {
          text: PropTypes.string.isRequired,
          fontSize: PropTypes.number,
        };
    
        function App() {
          return (
            <div>
              <Btn text="Save Changes" fontSize={18} />
              <Btn text="Continue" />
            </div>
          );
        }
        ReactDOM.render(<App />, root);
      </script>
    </html>

→ props에 타입을 지정해주어서 콘솔에서 오류 확인 가능 (다른 타입 작성하는 실수 방지)

4.3 Recap

위와 동일

#5 CREATE REACT APP

5.0 Introduction

→ create-react-app : React.js를 만드는 쉬운 방법

npx create-react-app 폴더명 : 리액트 앱 생성 명령어

→ npm start : 리액트 실행

→ package.json : 대부분의 내용이 담겨있음

→ 모든 폴더는 src 폴더 안에 위치

index.js : 가장 중요한 파일

→ 필요없는 파일 삭제 후 깨끗하게 시작 (App.js, index.js만 필요)

5.1 Tour of CRA

  • App.js
    import Button from "./Button";
    import styles from "./App.module.css";
    
    function App() {
      return (
        <div>
          <h1 className={styles.title}>Welcome back!!!</h1>
          <Button text={"Continue"} />
        </div>
      );
    }
    
    export default App;
  • App.module.css
    .title {
      font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
      font-size: 18px;
    }
  • Button.js
    import PropTypes from "prop-types";
    import styles from "./Button.module.css";
    
    function Button({ text }) {
      return <button className={styles.btn}>{text}</button>;
    }
    
    Button.propTypes = {
      text: PropTypes.string.isRequired,
    };
    
    export default Button;
  • Button.module.css
    .btn {
      color: white;
      background-color: tomato;
    }
  • index.js
    import React from "react";
    import ReactDOM from "react-dom/client";
    import App from "./App";
    
    const root = ReactDOM.createRoot(document.getElementById("root"));
    root.render(
      <React.StrictMode>
        <App />
      </React.StrictMode>
    );

npm install prop-types : prop types를 사용하기 위해 설치하는 명령어

→ style을 모듈로 사용함으로써 같은 btn이라는 이름을 사용해도 다르게 적용 가능
(랜덤 방식으로 자동 생성 기능 존재)

#6 EFFECTS

6.0 Introduction

  • App.js
    import { useState } from "react";
    
    function App() {
      const [counter, setValue] = useState(0);
      const onClick = () => setValue((prev) => prev + 1);
      console.log("call an api");
    
      return (
        <div>
          <h1>{counter}</h1>
          <button onClick={onClick}>click me</button>
        </div>
      );
    }
    
    export default App;

→ state가 변경될 때마다 리렌더링을 하게 되면 렌더링을 하고 싶지 않은 순간에도 진행

→ ex) API를 가져올 때 처음에만 렌더링하고 이후에 다시 정보를 가져올 필요 X

→ 첫번째 component render에서만 특정 코드들이 실행 (state 변화해도 코드 재실행 X)

useEffect 사용

6.1 useEffect

  • App.js
    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("call the API");
      };
      useEffect(iRunOnlyOnce, []);
    
      return (
        <div>
          <h1>{counter}</h1>
          <button onClick={onClick}>click me</button>
        </div>
      );
    }
    
    export default App;

→ useEffect : 두 개의 argument를 가지는 function
(1. 우리가 실행하고 싶은 코드 / 2. dependency(ies) : 리액트가 변화를 지켜볼 인자)

→ 코드가 딱 한번만 실행될 수 있도록 보호하는 역할

6.2 Deps

  • App.js
    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 [keyword, setKeyword] = useState("");
      const onChange = (event) => setKeyword(event.target.value);
    
      const iRunOnlyOnce = () => {
        // console.log("call the API");
        console.log("I run only once.");
      };
      useEffect(iRunOnlyOnce, []);
    
      useEffect(() => {
        // if (keyword !== "" && keyword.length > 5) {
        //   console.log("SEARCH FOR", keyword);
        // }
        console.log("I run when 'keyword' changes.");
      }, [keyword]);
    
      useEffect(() => {
        console.log("I run when 'counter' changes.");
      }, [counter]);
    
      useEffect(() => {
        console.log("I run when keyword & counter changes.");
      }, [keyword, counter]);
    
      return (
        <div>
          <input value={keyword} onChange={onChange} type="text" placeholder="Search here..." />
          <h1>{counter}</h1>
          <button onClick={onClick}>click me</button>
        </div>
      );
    }
    
    export default App;

→ useEffect를 사용하지 않았을 때 검색어를 입력할 때마다 모든게 리렌더링됨
(혹은 click 버튼을 누를 때마다 입력되어 있는 검색어를 같이 리렌더링)

useEffect(() => {
    console.log("SEARCH FOR", keyword);
  }, **[keyword]**);

→ 키워드가 변화할 때만 코드를 실행(리렌더링)

[] 처럼 두번째 argument가 비어있을 때, 지켜볼게 없기 때문에 처음 한번만 실행

if (keyword !== "" && keyword.length > 5) : 키워드가 없거나 짧을 때 실행 X 조건

[keyword, counter] : array이기 때문에 2가지의 변화를 확인할 수도 O

Memo VS useEffect

→ Memo : props가 변경되지 않았을 때 리렌더링 X

→ useEffect : props가 변경될 때 함수 실행
혹은 컴포넌트의 시작, 끝에만 실행

6.3 Recap

→ state를 변화시킬 때 component를 재실행

→ useEffect는 react.js가 동작하는 관점에서 방어막

6.4 Cleanup

  • App.js
    import { useState, useEffect } from "react";
    
    function Hello() {
      // function byFn() {
      //   console.log("bye :(");
      // }
      // function hiFn() {
      //   console.log("created :)");
      //   return byFn;
      // }
    
      useEffect(() => {
        console.log("hi :)");
        return () => console.log("bye :(");
      }, []);
      return <h1>Hello</h1>;
    }
    
    function App() {
      const [showing, setShowing] = useState(false);
      const onClick = () => setShowing((prev) => !prev);
      return (
        <div>
          {showing ? <Hello /> : null}
          <button onClick={onClick}>{showing ? "Hide" : "Show"}</button>
        </div>
      );
    }
    
    export default App;

{showing ? <Hello /> : null} : 코드를 숨기는 것이 아니라 destroy 시키고 새로 생성

useEffect(() => {
    console.log("created :)");
    **return** () => console.log("destroyed :(");
  }, []);

→ Cleanup function return : 함수인데 component가 destroy될 때 뭔가 할 수 있도록 해 줌

→ ex) 컴포넌트가 없어질 때 분석 결과를 보내고 싶으면 분석 API 사용 등

→ 자주 사용하지는 X

0개의 댓글