Intro
- useEffect
- Clean-up
예를 들어, 우리가 검색 api를 사용하려고 할 때 맨 처음 api를 호출해 데이터를 받아온다. 하지만 이후에 버튼을 클릭하든.. 어떤다 state가 변경될때마다 다시 그 api를 또 호출한다면? 매우 비효율적이다.
그래서 우리는 가끔은 특정 코드들이 처음 한번만. 즉 첫번째 컴포넌트의 render에만 실행되도록 하고 나중에 state가 변하더라도 그 코드들을 다시 실행되지 않도록 하고 싶다.
useEffect function
React에게 컴포넌트가 렌더링 이후에 어떤 일을 수행할지를 알려주는데, 아래의 예시처럼 특정 코드들을 특정한 때에만 실행되도록 하고 싶을때 사용할 수 있다.
useEffect 함수는 두 개의 인자(argument)를 가지고 있다.
useEffect(()=>{},[특정변수 혹은 오브젝트]);
첫 번째 인자는 우리가 실행시키고 싶은 코드(보통 함수를 넘겨주고 이 함수를 'effect'라고 부름)이고,
두 번째 인자는 dependencies로 react.js가 지켜보아야하는 것으로 그것들이 변화할 때, react.js가 코드를 실행시킨다. (인자에 리스트가 존재하면, 해당 리스트의 값이 변화될 때만 실행된다.)
두 번째 인자에 빈 배열 []을 주게되면(비어있다면_, react.js 가 지켜볼 대상(dependency)이 없기 때문에 코드가 한 번만 실행될 거라는 걸 의미한다. 즉, 변화에 대해 반응하지 않고 최초 렌더링 혹은 컴포넌트 해제 시 호출이 된다. 또한 배열을 넣어줄 수 있기 때문에 지켜볼 대상(특정변수 혹은 오브젝트)을 하나만 넣어주거나 여러 개를 넣어 줄 수도 있다.
useEffect(() => {
console.log("I run only once."); // 시작할 때 한번만 실행
}, []);
useEffect(() => {
console.log("I run when 'keyword' changes."); // 시작할 때 + keyword 변화시 실행
}, [keyword]);
useEffect(() => {
console.log("I run when 'counter' changes."); // 시작할 때 + counter 변화시 실행
}, [counter]);
useEffect(() => {
console.log("I run when 'keyword & counter' changes."); // 시작할때 + keyword, counter 둘 중 변화시 실행
}, [keyword, counter]);
Cleanup function
우리는 컴포넌트가 파괴(destroy)될 때 무언가를 하도록 하고 싶은 경우가 있다. ( 함수를 실행시킨다던지 데이터를 반환한다던지 등...)
useEffect는 컴포넌트의 렌더링 이후에 다양한 side effects를 표현할 수 있는데, effect에 정리(clean-up)가 필요한 경우에는 함수를 반환(return)해주면 된다.
React는 컴포넌트가 마운트 해제되는 때에 정리(clean-up)을 실행한다.
하지만 effect는 한번이 아니라 렌더링이 실행되는 때마다 실행되는데, React가 다음 차례의 effect를 실행하기 전 이전의 렌더링에서 파생된 effect를 정리하는 이유가 바로 이 때문이다.
React가 DOM을 업데이트 한 뒤 추가로 코드가 실행할 필요가 없으면 정리를 해줘야한다.
버튼을 누름으로써 Hello라는 문구가 보이고 사라지게하는 어플리케이션을 만들어보려고 한다. 여기서, 텍스트를 반환하는 Hello 컴포넌트는 더 이상 사용하지 않는 컴포넌트이기 때문에 해제해야 한다. 그렇지 않으면 메모리 누수가 발생해 시스템에 안좋은 영향을 미칠 수 있기 때문이다.
초기 렌더링 시 showing이라는 state 값이 true일 시 Hello 컴포넌트를 보여주고, false일 시 컴포넌트를 보여주지 않도록 한다. 이 어플리케이션의 동작원리는 다음과 같다.
- 맨 처음에 App 컴포넌트 렌더링 : showing값 false, Show 버튼만 출력
- Show 버튼을 클릭 => 클릭이벤트가 발생(showing값 false=>true) => state 값이 변경되었으니 App 컴포넌트 리렌더링 => Hello 컴포넌트 생성 => useEffect 함수 effect인 hiFn 함수 실행(created 로그) => Hello와 Hide 버튼 출력
- Hide 버튼을 클릭 => 클릭 이벤트가 발생(showing값이 true=>false) => state 값 변경되었으니 App 컴포넌트 리렌더링 => 이 전의 Hello 컴포넌트의 effect 클린업(bye 로그) => Show 버튼만 출력
import { useEffect, useState } from "react";
function Hello() {
function byFn() {
console.log("bye :(");
}
function hiFn() {
console.log("created :)");
return byFn; // component가 파괴될때 function을 실행하고 싶으면, 새로운 function을 return해야함
}
useEffect(hiFn, []);
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;
위 코드는 좀 복잡한 편이고, 보통은 useEffect 안에 모든 코드를 작성한다.
일반적인 함수로 정의하든, 화살표 함수로 정의하든 결과는 똑같다.
function Hello() {
useEffect(() => {
console.log("hi :)");
return () => console.log("bye :("); // function 리턴
}, []);
return <h1>Hello</h1>;
}
function Hello() {
useEffect(function (){
console.log("hi :)");
return function(){
console.log("bye :(");
}
}, []);
return <h1>Hello</h1>;
}
실행결과는 다음과 같다.
'WEB > React' 카테고리의 다른 글
[React] API 사용하기 (0) | 2022.02.02 |
---|---|
[React] 배열 State (0) | 2022.02.02 |
[React] Props (Memo, Props Types) (0) | 2022.01.28 |
[React] State (0) | 2022.01.28 |
[React] Component, JSX (0) | 2022.01.26 |