• [React] Effect 공부

    2022. 1. 16.

    by. 모모

    해당 게시물은 노마드코더 ReactJS로 영화웹서비스 만들기를 수강하면서 정리한 내용입니다.

    강의는 무려 무료!! 이므로 노마드코어를 검색해서 직접 들어보세요! 😁

    그리고 React를 들어가기 전에 HTML, CSS, Javascript에 대한 학습이 어느정도 되어있어야 합니다.

    무작정 시작하면 동시에 수많은 정보를 학습해야 하니 바닐라JS 부터 차근차근 학습하시길 바랍니다.


    0. 시작하기

    state편에서 state를 계속 change했고 state에 관련된 모든 것이 다시 실행되는 것을 볼 수 있었습니다.

    counter에 0이 아닌 새로운 값이 들어가는 것을 빼고는 똑같이 function이 다시 실행되는 것이죠.

    이것은 반복적인 실행입니다.

    계속 다시 render될 때마다 반복실행되어도 괜찮은 코드가 있을 수 있습니다. 하지만 그렇게 하지 않고 component가 처음 render될 때만 코드가 실행되도록 하고 싶을 수도 있습니다.

    state편에서 작성했던 코드는 state가 변할 때마다 해당 function이 실행됩니다. ( console.log로 확인해보세요. )

    API가 들어있다면 state가 변할때마다 해당 API도 계속 호출되는 불상사가 발생하는 것이죠.

    그렇다면 특정 코드를  첫 번째로 render할때만 실행시키는 방법은 무엇일까요?

     


    1. useEffect

    useEffect는 두 개의 argument를 가지는 function입니다.

    첫 번째 argument는 우리가 딱 한번만 실행하고 싶은 코드입니다. 두 번째 argument는 변하는 값을 특정하고 싶을 경우 사용합니다.

     

    1.1 import

    import { useEffect } from 'react';

     

    1.2 useEffect 첫 번째 argument만 사용해보기

    const iRunOnlyOnce = () => {
      console.log("run only once.");
    }
    useEffect(iRunOnlyOnce, []);

    state에서 작성했던 코드에서 useEffect 부분만 추가하겠습니다.

    import React, { useState, useEffect} from 'react';
    import './App.css';
    
    function App() {
      const [counter, setValue] = useState(0);
      const onClick = () => setValue((prev) => prev + 1);
      console.log("run all the time");
      const iRunOnlyOnce = () => {
        console.log("run only once.");
      }
      useEffect(iRunOnlyOnce, []); 
      return (
        <div>
          <h1>{counter}</h1>
          <button onClick={onClick}>Click me</button>
        </div>
      );
    }
    
    export default App;

    그리고 버튼을 눌러보면 run all the time만 콘솔창에 출력되는 것을 볼 수 있습니다.

    좀 더 단순하게 작성하는 방법도 있습니다.

    useEffect(() => {
      console.log("run!");
    }, []);

    즉, useEffect function은 코드가 딱 한번만 실행될 수 있도록 보호해주는 역할을 합니다. 딱 한번만 실행해주는겁니다.

    그렇기 때문에 useEffect를 사용하는 것입니다.

    state가 변화하든 변화하지 않든 코드가 단 한번만 실행될 것이라고 확신할 수 있습니다.

    어떠한 일이 일어나도 useEffect안에 있는 코드는 단 한번만! 실행되는 것입니다.

     

    1.3 useEffect의 두 번째 argument도 사용해보기

    검색 시스템을 만들어봅시다.

    import React, { useState, useEffect} from 'react';
    import './App.css';
    
    function App() {
      const [counter, setValue] = useState(0);
      const [keyword, setKeyword] = useState("");
      const onClick = () => setValue((prev) => prev + 1);
      const onChange = (event) => setKeyword(event.target.value);
      console.log("run all the time");
      useEffect(() => {
        console.log("call the api");
      }, []); 
      console.log("SEARCH FOR", 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;

    검색창에 특정 문구를 입력할때마다 SEARCH FOR [keyword]가 콘솔창에 뜰 것입니다.

    우리가 배운 effect를 활용해서 코드를 변경해봅시다.

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

    SEARCH FOR [keyword]가 딱 한번만 실행시키겠지요?

    counter가 변화할때가 아니라 keyword가 변할때만 해당 코드를 실행시키고 싶다면 두 번째 argument에 해당 key를 입력해주면 됩니다.

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

    이제 keyword가 변할 때 코드를 실행할 것입니다. 오직 keyword가 변화할때만 실행됩니다.

    빈 array를 써 주었을때 코드가 단 한번만 실행시키는 이유도 더 이상 지켜볼 변수가 없으니 단 한 번만 실행시키는 것입니다.

    useEffect(() => {
      if (keyword !== "" && keyword.length > 5) {
        console.log("SEARCH FOR", keyword);
      }
    }, [keyword]);

    다음과 같이 변경하면 keyword가 조건에 부합했을 때만 console.log를 실행시키는것을 볼 수 있습니다.

    정리해봅시다.

    // 기본적으로 실행
    console.log("run all the time");
    // 처음에만 실행
    useEffect(() => {
      console.log("run only once.");
    }, []);
    // keyword가 변할때만 실행
    useEffect(() => {
      console.log("run when 'keyword' changes.");
    }, [keyword]);
    // counter가 변할때만 실행
    useEffect(() => {
      console.log("run when 'counter' changes.");
    }, [counter]);
    // keyword와 counter 둘 중 하나가 변하면 실행
    useEffect(() => {
      console.log("run when 'keyword & counter' changes.");
    }, [keyword, counter]);

    이제 무언가 변화할때에 맞춰서 특정 코드를 실행시킬 수 있습니다.


    2. Cleanup Function

    많이 쓰이진 않는다고 합니다.

    function Hello() {
      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>
      );
    }

    해당 코드에서는 단순히 state가 바뀔 때 모든 component가 바뀌는 코드입니다.

    hello Component에 useEffect를 만들어줍시다.

    function Hello() {
      useEffect(() => {
        console.log("I'm here");
      }, []);
      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>
      );
    }

    어떤일이 일어날거같나요? 버튼을 누르고 Show로 변해 Hello가 보일때마다 console에는 I'm here이 출력되게 됩니다.

    즉 hello component를 hide할 때는 해당 component를 screen에서 지워주고 있었습니다. 그래서 다시 출력할때 console.log가 실행되게 되는것입니다. component를 없애거나 생성하고 있었던 것입니다.

     

    component가 create 될 때마다 effect가 실행되고 있고 component가 destory될 때도 코드를 실행되고 있습니다.

    숨기는 것이 아니라 아예 없애버리는 것입니다.

    destory할 때도 function을 작동시킬 수 있습니다.

    function Hello() {
      useEffect(() => {
        console.log("created!!");
        return () => console.log("distroyed..");
      }, []);
      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>
      );
    }
    return () => console.log("distroyed..");

    return하게 될 때 console창을 띄우게 하는 이것을 바로 Cleanup function이라고 부릅니다.

    단순한 function이지만 component가 destory될 때 뭔가를 할 수 있도록 해주는 것입니다.

    이것은 component가 없어질 때 어떤 분석결과를 보내고 싶어할 경우에 사용하는 등에 사용할 수 있습니다.

    function Hello() {
      function byFn() {
        console.log("bye..");
      }
      function hiFn() {
        console.log("hi!!");
        return byFn;
      }
      useEffect(hi, []);
      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>
      );
    }

    다음과 같이 사용할 수도 있습니다.

    하지만 이런식으로 function을 잘 사용하지 않습니다. 정말 특정한 케이스에만 사용합니다.


     

    useEffect는 언제 code를 실행할 지 선택권을 제공합니다.
    시작할 때만 code를 실행할 수 있고 무언가가 변화할 때, component가 파괴 될 때 code를 실행시키게 할 수 있습니다.

    댓글

Designed by Nana