티스토리 뷰

반응형

 이 포스팅은 https://nomadcoders.co/react-for-beginners강의를 보며 작성하였습니다.(무료!)

  이번 강의를 학습하기 전에 왜 이러한 것들이 필요한지 먼저 알아보도록 하자. 먼저 앞선 강의에서 배웠던 것을 활용해 똑같이 count를 세는 state를 만들어 보자.

import { useState } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const onClick = ()=> setValue((prev)=>prev+1);
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={onClick}>click me</button>
    </div>
  );
}

export default App;

counter를 state로 선언해 주고 onClick 함수를 만들어 counter의 수가 1씩 증가하도록 만들었다. 그리고 h1에서는 변화된 counter를 보여주며, 버튼을 하나 만들어 onClick event를 통해 클릭할 시 미리 만들어둔 함수를 연결하여 setValue를 통하여 counter를 증가시켜 주었다.

잘 작동한다. 하지만 이러한 변화를 가져다주는 이유는 무엇일까? console.log를 통해 출력해 보면, 처음 페이지를 불러올 때 랜더링이 일어나고 클릭할 때마다 추가적으로 랜더링이 일어난다. 

 이러한 랜더링은 state값이 변화할 때 모든 함수들이 재 실행되기 때문이다. 보통은 이런 랜더링이 문제가 되지 않을 것이다. 하지만, 만약 API의 호출이 있는 함수일 경우는 어떨까?

 처음의 페이지가 불러올 때 API를 요청하여 View를 보여주는 것은 아주 좋다. 하지만, 클릭을 할 때마다 API요청을 보내게 된다면 성능적으로 문제가 될 수 있을 것이다. 때문에 이러한 함수들이 있다면 페이지를 불러오는 처음 화면 한 번만 실행되게 제한하는 것이 이상적일 수 있다. useEffect를 통해 이러한 문제를 해결할 수 있다.

 

 useEffect는 두 개의 argument를 가지는 function이다. 여기서 첫 번째 argument가 우리가 딱 한 번만 실행하고 싶은 코드이다. 두 번째 argument는 뒤에 설명할 것이다.

 다시 항상 실행되는 구문을 만들고 한 번만 실행하고 싶은 함수도 만들어서 비교를 해보자. 

import { useState } 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("I run only once.")
  }
  useEffect(iRunOnlyOnce, []);
  return (
    <div>
      <h1>{counter}</h1>
      <button onClick={onClick}>click me</button>
    </div>
  );
}

export default App;

console.log를 통해 "I run all the time"구문은 이 전과 똑같이 랜더링이 일어날 때마다 계속 작동할 것이다. 하지만 useEffect로 실행한 iRunOnlOnce의 함수를 보자.

처음 화면에서는 두 함수가 잘 불러와진 것을 볼 수 있다.

하지만, 버튼을 클릭할 때에는 "I run all the time"구문만 출력되는 것을 확인할 수 있다. iRunOnlOnce함수는 더 이상 실행되지 않는다. 구문을 조금 더 간결하게 다음과 같이 정리할 수 있다.

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

 함수를 따로 생성하지 않고 useEffect 안에 => 함수를 이용해 구문을 적었다. 똑같이 작동하며 "CALL THE API"는 한 번만 작동하는 것을 확인할 수 있다.

 

여기에 input tag를 이용해 검색창을 하나 만들어 보자. 먼저 state로 선언해 주고 함수를 연결해 입력창의 상태가 변화하면 그 값들을 가져온다.

import { useEffect, useState } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onChange = (event)=> {setKeyword(event.target.value)};
  const onClick = ()=> setValue((prev)=>prev+1);
  console.log("I run all the time");
  useEffect(()=>{console.log("CALL THE API...")}, []);
  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;

하지만 이렇게 state값을 넣어 주면 input값이 변화할 때마다 console.log가 찍히게 된다.

 여기서 문제점은 input값을 줄 때와 버튼을 클릭할 때 모두 state의 값이 변화하게 되고 두 가지의 경우가 모두 리랜더링이 되어 console.log를 동작시켜 버린다. 그래서 이러한 코드에서 특정한 부분만이 변화했을 때 원하는 코드들을 실행할 수 있는 방법이 필요하다.

 우선 useEffectf를 사용해 똑같이 처음 한 번만 랜더링 되게 만들어 준다. 그리고 두 번째 argument에 변화하는 값인 keyword를 입력해 준다. 

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

 하지만 입력값이 아무것도 없다면 검색할 필요가 없기 때문에 다음과 같은 조건도 걸어준다.

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

이제 react를 실행해 보면

"CALL THE API"는 처음 한 번만 작동하고, 클릭 및 input값이 바뀔 때는 "I run all the time"이 잘 작동하는 것을 볼 수 있다. 또한 input값이 5글자 이상이 넘어가면 "SEARCH FOR"함수가 작동하는 것을 볼 수 있다. 이렇게 하나의 state값이 바뀌면 모두 작동하던 함수들이 각각의 상황에 맞게 실행될 수 있게 조정할 수 있다. 조금 더 심플한 예시로 변경시켜 준다면

  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]);

 

처음 한번, input값이 변경될 때, 버튼을 눌렀을 때 각각 함수들을 실행할 수 있도록 분리할 수 있다.

git : https://github.com/leesulgi66/React_for_Beginners/commit/01ad829577be87de8de80179cad2b773bea13a84

 

 정리해 보면 Effect는 두 개의 argument를 가지고 첫 번째는 우리가 실행시키고 싶은 코드를 받고, 두 번째는 dependencies라고 불리며 react.js가 지켜봐야 할 것들이다. 그리고 그것들이 변화할 때 코드는 실행된다. 이렇게 코드를 언제 실행할지 선택권을 가질 수 있게 된다.

 

 마지막으로 Effect의 Cleanup function이라는 것을 배워보자. (많이 쓰이지 않을 수도 있다.)

import { useEffect, useState } from "react";

function Hello() {
  return <h1>Hello</h1>;
}

function App() {
  const [showing, setShowing] = useState(false);
  const onClick = ()=>{setShowing((pre)=>!pre)};
  return (
    <div>
      {showing ? <Hello /> : null}
      <button onClick={onClick}>{showing ? "hide" : "show"}</button>
    </div>
  );
}

export default App;

간단하게 버튼을 하나 만들고 state값을 이용하여 Hello라는 h1을 보여주는 컴포넌트를 만들었다.

그리고 useEffect를 이용하여 show를 눌러 Hello가 보일 때 작동하는 함수 하나를 설정해 준다.

function Hello() {
  useEffect(()=>{
    console.log("Im here!")
  }, []);
  return <h1>Hello</h1>;
}

show 버튼을 누를 때만 아주 잘 작동한다. 이렇게 필요한 컴포넌트가 불러와질 때 실행되는 함수를 만들 수 있는데, 반대로 컴포넌트가 사라질 때도 함수를 동작시킬 수 있다. 일단 이해는 잘 가지 않지만 return 구문을 하나 추가해 준다.

function Hello() {
  useEffect(()=>{
    console.log("created :)");
    return ()=>console.log("destroyed :("); // 함수 형태로 console.log를 return해준다.
  }, []);
  return <h1>Hello</h1>;
}

 짜잔! 이제 컴포넌트가 사라질 때에도 함수가 작동한다. 이러한 함수를 Creanup function이라고 한다. 즉 컴포넌트가 사라질 때에도 우리는 어떠한 함수를 작동시킬 수 있다. 

 조금 더 구문을 정리해 보면 다음과 같다.

import { useEffect, useState } from "react";

function Hello() {
  function byFn() {
    console.log("Bye :(")
  } 
  function hiFn() {
    console.log("Hi :)")
    return byFn;
  } 
  useEffect(hiFn, []);
  return <h1>Hello</h1>;
}

function App() {
  const [showing, setShowing] = useState(false);
  const onClick = ()=>{setShowing((pre)=>!pre)};
  return (
    <div>
      {showing ? <Hello /> : null}
      <button onClick={onClick}>{showing ? "hide" : "show"}</button>
    </div>
  );
}

export default App;

 Hellow function 안에는 두 개의 function을 가지고 있다. useEffect에 hiFn을 등록해 주면 우리는 show가 클릭될 때 hiFn이 작동하는 것을 알 수 있었다. 그리고 여기 hiFn이 다시 새로운 byeFn을 return 값으로 가지고 있게 되면 컴포넌트가 사라질 때에도 함수를 작동시킬 수 있다. 

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함