WEB/React

[영화 웹] #6. EFFECTS

Harimad 2022. 1. 28. 19:08

노마더코드 깃 히스토리: https://github.com/nomadcoders/react-for-beginners/commits/master

#6.0 Introduction

문제점:

button 의 onClick 함수가 실행되면서

state를 변경할 때 해당컴포넌트 code들을 rerendering한다.

한번만 받아도 될 정보의 경우에도 리렌더링에 의해 계속해서 불려지는 문제가 발생한다.

최초 한번만 필요한 정보를 계속해서 리렌더링 하는 것은 코드의 규모가 클 경우 비효율적이기 때문이다.

 

목표:
첫 번째 랜더링때에만 API를 통해 가져온 데이터 코드가 실행되고

다른 State변화에는 실행되지 않도록 만들고 싶다.

 

#6.1 useEffect

https://ko.reactjs.org/docs/hooks-effect.html

 

Using the Effect Hook – React

A JavaScript library for building user interfaces

ko.reactjs.org

useEffect ( callback f ,  [] )

: 대표적인 사용법 => API를 딱 한번만 호출하고 그 뒤로는 다시는 호출하기 싫은 경우
useEffect가 컴포넌트의 첫 번째 렌더 시점에 콜백 함수 호출
그리고 상태를 변화시키면 콜백함수는 호출되지 않는다

//App.js
import {useState, useEffect} from 'react';

function App() {
  const [counter, setCounter] = useState(0);
  const onClick = () => setCounter((prev) => prev + 1);

  console.log('I run all the time'); //onClick함수실행으로 state가 변하면 console이 계속 동작함(비효율)

  useEffect(() => {
    console.log('I run only once.');  //state가 변해도 더이상 재실행 되지않음!!
  }, []);

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

 

#6.2 Deps (useEffect 의 두번째 배열 인자)

useEffect( 콜백함수, [] )

: 처음 랜더링때 한번만 호출 시키고 싶을때나 특정state가 변할때 코드를 실행하고 싶을때 사용한다.

 

import {useState, useEffect} from 'react';

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

  console.log('항상 실행');

  useEffect(() => {
    console.log('처음 한번만 실행');
  }, []); //배열이 비어있으면, 코드가 1번만 실행됨

  useEffect(() => {
    console.log('keyword 바뀔때만 실행');
  }, [keyword]); //keyword가 변화할 떄 코드를 실행하고 싶다면, 배열에 keyword 기입

  useEffect(() => {
    console.log('counter 바뀔때만 실행');
  }, [counter]); //counter가 변할때만 실행

  useEffect(() => {
    console.log('keyword & counter 바뀌면 실행');
  }, [counter, keyword]); //counter, keyword가 변할때 실행

  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;

 

 

💯 새롭게 배운 내용 정리

 

리액트를 사용하는 이유: 최소 단위의 렌더링을 위해

useState(): 변수, 변수를 제어하는 함수로 구성되며 변하는 값을 제어, 해당 부분의 리렌더링을 위함
props: 태그의 속성 값을 함수의 인자 처럼 컴포넌트에 값을 전달해준다.
useEffect(): 코드의 실행 시점을 관리할 수 있는 선택권을 얻는 방어막 같은 존재, 디펜던시가 없을 경우 최초 1회 실행, 있을 경우 해당 값이 변할 경우 실행한다. 이 때 디펜던시는 여러개 입력이 가능하다.

🏴 부모 컴포넌트에서 리렌더링이 일어날 경우 모든 자식들이 리렌더링이 된다.(we can use 'memo')
🏴 propType을 설치하고 props의 타입을 지정해 줄 수 있다. 이 때 isRequired로 필수값을 지정 가능

 

React.js는 새로운 정보를 자동적으로 refresh 해준 다는 점에서 편리하다.
하지만, 때로는 이러한 기능이 불필요할 때가 있다.
예를 들어, 검색창을 이용하는데 버튼 창이 리렌더링 되는 상황이 그렇다.
이렇게 불필요한 리렌더링을 피하기 위해 React.js가 따로 준비한 것이 바로 useEffect이다.
useEffect는 실행시키고자 하는 함수와 React.js가 이벤트를 주시하게끔 하는dependency로 이루어져있다. 즉, 내가 원하는 부분을 지정하여 그 부분만을 변화시킬 수 있는 것이다.
버튼을 누르면 버튼만, 검색창을 이용할 때는 검색창만 리렌더링 되는 것처럼 말이다.

 

#6.4 Cleanup

App컴포넌트에서 Hello컴포넌트를 생성할때

Hello컴포넌트안에서 useEffect함수에 의해서 한번 콜백함수인 console.log('안녕')이 동작한다.

App컴포넌트에서 Hello컴포넌트를 제거하고, 다시 Hello컴포넌트를 생성하면 useEffect의 콜백함수가 재실행된다.

주목할만한 점은

컴포넌트가 destroy될 때도 코드를 실행할 수 있는 것이다.
useEffect함수의 콜백함수에 return값으로 함수를 만들어주면 된다.

 

useEffect함수는 함수(콜백)를 받고, dependency가 변화할 때 호출되는 함수이다.

dependency가 비어있으면

컴포넌트가 처음 생성될 때

함수가 호출된 후 다시는 호출 되지 않는다.
그래서 컴포넌트가 파괴될 때도 함수를 실행하고 싶으면

useEffect함수의 콜백함수에 새로운 함수를 return(cleanup) 하면 된다.

function Hello() {
  useEffect(() => {
    console.log('안녕:)'); //Hello컴포넌트 생성시 실행
    return () => console.log('잘가:('); //Hello컴포넌트가 파괴될때 리턴함수(CleanUp함수) 실행
  }, []); //deps가 비었으니 Hello컴포넌트 생성시 한번만 Callback함수 실행

  return <h1>Hello</h1>;
}

 

내가 이해한 컴포넌트의 useEffect 동작방식

Hello 컴포넌트
생성(Rendering) 파괴(Cleanup) 재생성(reRendering) 파괴(Cleanup) 반복...
useEffect실행 return Callback useEffect재실행 return Callback  

 

import { useState, useEffect } from 'react';

function Hello() {
  useEffect(() => {
    console.log('안녕:)');
    return () => console.log('잘가:(');
  }, []);

  return <h1>Hello</h1>;
}

function App() {
  const [showing, setShowing] = useState(false);
  const onClick = () => setShowing(prev => !prev);
  return (
    <div>
      {showing ? <Hello></Hello> : null}
      <button onClick={onClick}>{showing ? 'Hide' : 'Show'}</button>
    </div>
  );
}

export default App;


참고

https://simsimjae.tistory.com/401

 

useEffect 완벽 가이드 - 2편, 의존성 배열 deps와 클린업 함수

useEffect 완벽 가이드 - 1편 읽고 오기 이제 우리는 함수형 컴포넌트 내부 함수에서 state, props를 참조할때 이전 값을 가져오는 현상이 발생하는 원인에 대해서 알게 되었습니다. 그럼 이제 최신 상

simsimjae.tistory.com