[ReactJS로 영화 웹 서비스 만들기] Chapter06. EFFECTS

IRISH·2024년 4월 11일

ReactJS-Movie-Web-Service

목록 보기
5/23
post-thumbnail

6.0 Introduction

  • 학습 일자 : 240328
  • 결과 목차에 있는 내용부터 먼저 보는 것이 좋을 듯!

코드

⇒ index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(<App />, document.getElementById("root"));
  • console창에 render가 두번씩 뜨는 현상이 있는데, index.js에서 React.StrictMode 태그를 삭제 하시면 됩니다.
  • StrickMode는 create-react-app으로 설치를 하시면 기본적으로 생성이 되어있는 태그인데해당 태그로 감싸져 있는 경우에는 코드의 문제를 감지하고 경고하기 위해서 구성 요소를 두 번 렌더링 한다고 합니다.(개발용이 아닌 프로덕션용)

⇒ App.js

import { useState } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const onClick = () => setValue((prev) => prev + 1);
  console.log("render");

  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me</button>
    </div>
  );
}

export default App;
  • const [counter, setValue] = useState(0);
    • 리액트 앱으로 하는 중이라 앞에 React 안붙여도됨
  • 리렌더링 될 때마다 반복실행되어도 괜찮은 코드도 있을 테지만, 컴포넌트가 처음 render 될 때만 코드가 실행되길 원할 수 도 있다. 예를들어, API로 외부 데이터를 가져올 때 컴포넌트 처음 렌더링되는 그 순간에만 API 요청을 하고 이후에 state가 변화할 때는 그 API에서 똑같은 정보를 가져오고 싶지는 않을 것이다.
    • 이렇게 특정 코드들이 첫번째 component render에서만 실행되게 하려면? => useEffect !!
  • useEffect()
    • 처음 render시에만 실행되게끔. like API
  • useMemo()
    • rerender시 데이터가 같다면 render안함.

결과

  • 이전 강의에 있었던 index.js의 React.StrictMode 태그를 지우지 않으면, Click me 버튼 클릭을 할 때마다 render 값을 남기는 log가 Console창에 2번 찍힘
    • 없애면, 문제 없음
  • 지금은 Click me 버튼을 통해서 render라는 값을 Console 창에 log로 남기고 있는 상황.
    • 즉, 클릭을 하면 새로 렌더링이 발생하고 있기 때문에 console 창에 render 값이 증가하고 있는 것
  • 강의에서는 이것을 API로 비유했을 때 어차피, 화면의 특정 부분에서 값이 변경되어 렌더링이 발생해도 API의 결과는 처음과 동일하면??? 굳이 이것을 re렌더링 할 필요가 없다고 언급!
    • 이것을 다음 강의에 이어서 진행!

6.1 useEffect

  • 학습 일자 : 240328
  • 특정값을 reRedering을 했을 때, 변하지 않는 항목들은 reRedering이 되지 않도록 useEffect를 활용해보자!

코드

⇒ App.js

import { useEffect, useState } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const onClick = () => setValue((prev) => prev + 1);
  console.log("i run all the time");
  useEffect(() => {
    console.log("CALL THE API.....");
  }, []);

  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me</button>
    </div>
  );
}

export default App;
  • console.log("i run all the time");
    • 이 친구는 버튼을 클릭을 할 때마다 reRendering
  • console.log("CALL THE API.....");
    • 이 친구는 버튼을 클릭해도 그대로 있음
    • 이유 : useEffect()
  • useEffect()
    • 두 개의 argument를 가지는 함수
    • 첫 번째 argument는 우리가 딱 한번만 실행하고 싶은 코드
    • 두 번째는 [] 배열을 넣어줌
  • useEffect가 컴포넌트의 첫 번째 렌더 시점에 iRunOnlyOnce 함수 호출
    • 그리고 상태를 변화시키면 iRunOnlyOnce는 호출되지 않음
    • 즉, 한번만 렌더링 됨
    • 단순화 하여 useEffect(() => {console.log("CALL THE API")},[]); 써도 됨

결과

  • i run all the time 와 CALL THE API 모두 처음 렌더링 시에는 출력
  • 하지만, 버튼을 클릭할 때
    • i run all the time 는 계속 리렌더링이 되지만
    • CALL THE API 는 안된다!
      • useEffect의 효과!!!

6.2 Deps

  • 학습 일자 : 240329
  • useEffect() 심화

코드

⇒ App.js

import userEvent from "@testing-library/user-event";
import { useEffect, useState } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onClick = () => setValue((prev) => prev + 1);
  const onChange = (event) => setKeyword(event.target.value);

  useEffect(() => {
    console.log("i run only once.");
  }, []);
  useEffect(() => {
    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 글자를 타이핑할 때마다 API를 새로 호출하지 않고 한번만 호출해준다.
  • search keyword에 변화가 있을 때 만! marvel영화를 검색하고 싶을 때, 즉 특정한 코드만 변화했을 때 원하는 코드들을 실행할 수 있는 방법
    • useEffect(() => {console.log("SEARCH FOR", keyword);}, []);
    • 이렇게 실행하면 1번만 됨
    • 그리고 []자리에 keyword 써줌
      • {console.log("SEARCH FOR", keyword);}, [keyword ]);
      • keyword가 변화할 때 코드를 실행할 거라고 react.js에게 알려주는 것.
      • 이것이 바로 빈 array를 써주었을 때 코드가 단 한번만 실행되는 이유임
      • react가 지켜볼 게 아무것도 없으니 처음 한번만 실행되는 것
  • useEffect(() => {console.log("I run when 'keyword & counter' changes.")}, [keyword, counter]);
    • 2개도 가능

6.3 Recap

  • 학습 일자 : 240329

내용

  • 리액트를 사용하는 이유: 최소 단위의 렌더링을 위해
  • useState(): 변수, 변수를 제어하는 함수로 구성되며 변하는 값을 제어, 해당 부분의 리렌더링을 위함
  • props: 태그의 속성 값을 함수의 아규먼트 처럼 컴포넌트에 값을 전달해준다.
  • useEffect(): 코드의 실행 시점을 관리할 수 있는 선택권을 얻는 방어막 같은 존재, 디펜던시가 없을 경우 최초 1회 실행, 있을 경우 해당 값이 변할 경우 실행한다. 이 때 디펜던시는 여러개 입력이 가능하다.
    • useEffect는 state의 상태를 감지 변경이 있을 때란 해당 컴포넌트를 랜더링한다.
    • useState(function(), []) [] 로 3가지 경우의 수 존재 ex) a, b 스테이트
    • 빈 배열을 넣는 경우, 최초 1회 랜더링 될 때만 실행한다.
    • [a] 하나의 state만 넣는 경우 a가 변경될 경우만 랜더링한다.
    • [a, b] a나 b중 하나가 값이 변경 될 때 랜더링한다.

🏴 부모 컴포넌트에서 리렌더링이 일어날 경우 모든 자식들이 리렌더링이 된다.(we can use memo)

🏴 propType을 설치하고 props의 타입을 지정해 줄 수 있다. 이 때 isRequired로 필수값을 지정 가능

6.4 Cleanup

  • 학습 일자 : 240331

내용

  • https://ko.reactjs.org/docs/hooks-effect.html#effects-with-cleanup
    • effect에서 함수를 반환하는 이유는 무엇일까요?
      • 이는 effect를 위한 추가적인 정리(clean-up) 메커니즘입니다. 모든 effect는 정리를 위한 함수를 반환할 수 있습니다.
    • React가 effect를 정리(clean-up)하는 시점은 정확히 언제일까요?
      • React는 컴포넌트가 마운트 해제되는 때에 정리(clean-up)를 실행합니다.
        • 하지만 강의에서 보았듯이 effect는 한번이 아니라 렌더링이 실행되는 때마다 실행됩니다.
      • React가 다음 차례의 effect를 실행하기 전에 이전의 렌더링에서 파생된 effect 또한 정리하는 이유가 바로 이 때문입니다.

코드

⇒ App.js

import userEvent from "@testing-library/user-event";
import { useState, useEffect } from "react";

function Hello() {
  /* cleanup -> 니꼬쌤 왈 : cleanup을 React 개발 시 자주 사용 X */
  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;
profile
#Software Engineer #IRISH

0개의 댓글