리액트

React 003 : useEffect

always_yoki 2023. 5. 22. 17:56

개요

 

1. useEffect

 


1. useEffect의 용법

   들어가기 전에 _  데이터를 입력받아 저장하거나, 저장된 데이터를 화면으로 불러오기 위해서는, 데이터베이스와 소통해줄 백엔드가 필요하다. 그러나 프론트엔드 공부 목적에서는 백엔드까지 구현을 할 순 없기 때문에 json-server와 같은 패키지를 통해 프로토타입 웹사이트를 만들어 볼 수 있다.useEffect 사용도 json-server의 API를 통해사용해볼것이다.

 

  우리가 필요로 하는 데이터도 결국은 어떠한 상태값이다.  Create Update Delete Read 를 하기 위해서는 데이터를 항상 갱신을 해야하는데, 데이터가 변한 상태를 끌어당겨 와야한다는 것이다.

 

  그리고 리액트에서 상태값을 변경할때는 useState를 사용한다. useState가 지닌 핵심기능이, UI를 업데이트 시켜주기 때문이다.(리액트는 임의로 컴포넌트를 재실행하지 않으며, useState를 통해 상태값이 변했을때 컴포넌트를 재 실행해 UI를 업데이트한다.)

 

  그러니까 데이터가 변경되었을때, 변경된 데이터를 화면에 보여줘야 한다면 useState를 이용해 상태를 변경시켜줌으로써 컴포넌트를 재시작해 새로운 UI를 불러다가 올 수 있는거다.  그런데!!! 공부하기로는  fetchAPI 를 통해 서버와 통신하여 데이터를 받아왔는데, 이 값을 그대로 setState 해버리면 컴포넌트가 재실행되면서 다시 fetch가 실행되고... 무한반복에 빠진다. 어떻게 하면 적절하게 컴포넌트의 재실행을 막을까?

 

이럴때 사용하는 것이 useEffect이다. 내가 배우는 두번째 Hook!!

 

useEffect()  는 부수효과를 래핑하는데 사용하며 값을 반환하지 않는다. 아래의 예시를 보자.

useEffect(()=>{
	async function fetchPosts(){
    const response = await fetch('http://localhost:8080');
    const resData = await response.json();
    setPosts(resData);
    }
    fetchPosts();   
},[])

useEffect 를 import 해준다음, 이렇게 사용해주었다. useEffect는 두개의 인자를 필요로 하는데, 첫번째 인자는 함수요 두번째 인자는 배열이다. 

첫번째 인자로 들어간 함수를 보자. 이 첫번째 함수는 function fetchPosts를 중첩하고있다.

한번 래핑해준것이다. 왜냐하면, async-await 속성때문에 그렇다.

fetch를 통해 서버와 통신하면 얼마간 시간이 걸린다. 그런데 자바스크립트가 동기적으로 작동해 데이터를 불러오기도 전에 다음 코드를 실행해 버린다면, 데이터를 받아와서 할당을 해줘야하는데 값이 없는채로 할당이 되어버린다 .우리가 원하는 작동방식이 아닌것이다! 이런것을 방지하기 위해, 즉 비동기적 작동을 해주기 위해 사용하는 ascyn와 await은 Promise를 반환한다. 

여기서 한가지 문제가 더 발생하는 것이다.

모종의 이유로, useEffect에 전달되는 첫번째 인자 함수는  프라미스를 반환하면 안된다!

그런데 fetch하기 위해서 async를 

 

useEffect(asnyc ()=>{..})

이런식으로 함수인자에 적용시켜버리면 useEffect의 효과함수는 프로미스를 반환해버리니.. 안될일!

그래서 한번 더 중첩을 시켜준다.

첫번째 예시처럼 function 하나를 더 만들어  그 함수에 async와 await을 적절히 사용해주면

useEffect가 인수로 받는 함수 자체에는 영향을 끼치지 않는것이다.

그러니 그렇게 만들어 준 함수를 fetchPosts() 로 한번 호출해주면, 효과함수는 그저 비동기방식으로 작동하는 함수를 호출하는 코드를 가지기 때문이다. 이렇게 까지 작성했다면

useEffect() 훅은 안에 있는 효과함수가 컴포넌트 함수가 실행될 때 마다 함께 실행되지 않도록 해줌으로써 무한루프를 막아준다. 

 

다시 한번! useEffect 훅을 사용하는 이유는 useState에 의한 컴포넌트 재실행으로 인한 무한루프를 막기 위함이다!!

 

그럼 정확히 언제 어떻게 실행될까?

그것이 바로, 두번째 인자로 '배열'을 전달하는 이유이다.

 

배열에는 효과함수를 실행 할 의존성을 정의한다. 변수든 함수든 효과함수 바깥에 정의된 것이라면 뭐든 쓸 수 있으며, props을 통해 전해 받은 부모컴포넌트에 있는 변수나 함수나 모두 괜찮다.

 

useEffect는 그렇게 배열에 정의 해놓은 변수 또는 함수가 변경될 때 마다 변경된 값을 받아서 효과함수를 재실행한다.

위의 코드에서는 빈 배열을 넣었는데, 그말인 즉슨 의존성이 없다는 뜻이므로 효과함수는 두번 실행되지 않는다.

단지 컴포넌트가 처음 렌더링 될 때 단 한번 실행한다!

 

 

요약

1. useEffect가 인자로 받는 함수는 프로미스를 반환하면 안된다. 아무것도 반환하지 않거나 클린업 함수를 반환해야한다.

2. 그렇기 때문에 useEffect의 인자함수 앞에는 async를 붙일 수 없다. async를 붙이면 프로미스로 반환되기 때문.

3. 그러니 중첩함수를 만들어 async-await를 쓰면 된다.

 

 

 

 

 

복습 Quiz

useEffect는 어떤 경우에 사용되는 훅일까요?
useEffect에는 어떠한 인자가 전달되어야 하고, 각각의 역할은 무엇인가요?
useEffect의 효과함수는 중첩함수를 가질수 있나요?