useState()와 useEffect()?
useStates와 useEffect는 React.js가 JS DOM을 대체할 수 있었던 가장 핵심적인 기능이다.
모던 웹은 정적 정보만을 제공하지 않고, 인터페이스를 통한 동적 상호작용을 통해 현재 페이지에 그려지는 요소의 상태를 표현한다.
이를 다루기 위해 라이브러리 없이 JS DOM으로만 이벤트를 처리할 때, 해당 요소를 정의, 로딩, 이벤트 정의, 이벤트 핸들링 등의 개념이 절차적 프로그래밍과 같이 코드로 작성되어야 했다.
하지만, useStates()와 useEffect()는 이러한 상태(state)를 변수에 담아 관리하고, 컴포넌트의 생명주기를 의존성 배열이나 조건부 렌더링 등을 통해 관리할 수 있다는 장점이 있다.
use~()이라고 하는 모든 리액트의 함수는 Hooks라는 이름으로 정의된다.
이 때, Hook이라는 개념은 리액트의 프로그래밍 전반에 대한 개념으로 이해되기보다는, Class형 컴포넌트에서 활용되는 메서드와 대비하여 이해되는 것이 더 효율적이다.
// 함수형 프로그래밍 Hooks, 클래스형 프로그래밍 메서드 :
useStates() 기본문법
useStates()의 기본문법은 무시무시한 React Hook이라는 정의와 달리 상당히 단순하다.
먼저 리액트에서는 어떤 JS 자체 메서드나 기능 외에 따로 정의된 기능을 활용하려면 import문을 통해 받아와야 하기 때문에 다음과 같은 useStates를 받아온다.
import { useState } from "react";
이후 상태를 관리하고자 하는 경우의 수를 파악한 뒤 해당 경우의 수를 정의해준다.
const [state, setState] = useState(initialValue)
// state는 현재 상태의 값이 담긴 변수이다. === 이것도 변수이니
// setState는 아직 상태가 담기지 않는 값이지만, 함수 내에서 할당해주는 과정을 통해 새로 변화된 상태를 담을 수 있다.
// initialValue는 컴포넌트가 마운트되면서 할당되는 초기 상태를 의미한다.
상태가 변경되면, 마운트된 컴포넌트가 state를 setState로 변경한 뒤 정의된 컴포넌트 자체를 재렌더링 한다.
** React 컴포넌트의 생명주기 : Mount vs Rendering
여기서 중요한 개념이 React 컴포넌트의 생명주기에 관한 내용이다.
React는 컴포넌트는 크게 생성 / 업데이트 / 소멸 3가지의 생명 주기를 갖는다.
위의 생성 / 업데이트 / 소멸은 눈에 보이는 페이지를 기준으로 작성한 것이고, 실제 사용되는 용어는 마운트 / 업데이트 / 마운트 해제이다.
1. 생성(Mount) : 컴포넌트가 생성되어 JSX 문법을 통해 DOM에 삽입되어 렌더링된다.
*컴포넌트가 생성되는 경우는 아주 많지만, 최초에 페이지를 들어갈 때 + 새롭게 글을 포스팅을 할 때 2가지를 예시로 들 수 있다.
2. 업데이트(Update) : 컴포넌트의 상태가 변경되어, 해당 상태를 렌더링한다.
*이와 같이 컴포넌트는 상태가 변경될 때마다 해당 컴포넌트 자체가 언마운트 되지 않고 새롭게 변화된 값으로 완전히 재렌더링을 한다.
3. 소멸(Unmount) : 컴포넌트가 페이지 내에서 동적 상호작용 혹은 조건부 렌더링 등의 작용을 통해 소멸한다.
위의 개념을 바탕으로 버튼을 누를 때마다 "배고픔 -> 치킨을 시킴 -> 맛나게 먹음 -> 행복함"의 4가지 상태를 업데이트하는 컴포넌트를 예시로 작성했다.
import React, { useState } from "react";
function isHungry() {
const [state, setState] = useState("배고프다");
// state === 내부 상태 값
// setState === 상태 설정 함수
// setState는 state와 같이 있어 변수로 오해하기 쉽지만, 사실 state라는 변수에 새로운 상태를 재할당하고 컴포넌트 재렌더링을 지시하는 "함수"이다.
const handleClick = () => {
// switch문은 여러 상태를 순차적으로 변경시킬 때 사용하는 함수일 뿐!
switch (state) {
case "배고프다":
setState("치킨을 시킨다"); // 상태 설정 함수로 "치킨을 시킨다" 상태로 변경시킨다.
break;
case "치킨을 시킨다":
setState("맛있게 먹는다");
break;
case "맛있게 먹는다":
setState("행복하다");
break;
case "행복하다":
setState("배고프다");
break;
default:
break;
}
};
return (
<div>
<p>{state}</p>
<button onClick={handleClick}>배고프면 클릭하세요</button>
</div>
);
}
export default isHungry;
useEffect() 기본문법
useEffect()의 기본문법 또한 useState() 기본문법과 같이 상당히 단순하다. (기본문법만..)
import { useEffect } from "react"
useEffect(
const didUpdate = () => {return 값}
);
useEffect는 컴포넌트 내부의 함수에 의한 변화가 아닌, 컴포넌트 외부에서 일어난 변화를 제어하기 위해 사용된다.
컴포넌트 외부에서 일어나는 변화도 아주아주 많지만, 대표적인 경우는 다음과 같다.
1. 외부 API에서 데이터를 비동기적으로 받아올 때
2. 컴포넌트의 마운트 / 언마운트 상황
3. 비동기적으로 타이머를 설정 및 제거할 때
이와 관련된 대표적인 API 데이터 수신 사례인 "오늘 제주도의 날씨"를 axios를 활용하여 받아오는 상황에 대한 예시를 작성해봤다.
import React, { useState, useEffect } from "react";
import axios from "axios";
function JejuWeather() {
const [weather, setWeather] = useState(null);
useEffect(() => {
const API_KEY = "YOUR_API_KEY_HERE";
const API_URL = `https://api.openweathermap.org/data/2.5/weather?q=Jeju&appid=${API_KEY}&units=metric`;
axios
.get(API_URL)
.then((res) => {
setWeather(res.data);
})
.catch((error) => {
console.error(error);
});
}, []);
if (!weather) {
return <div>Loading...</div>;
}
return (
<div>
<h1>제주날씨</h1>
<p>날씨: {weather.weather[0].description}</p>
</div>
);
}
export default JejuWeather;
이 때 useEffect(axios함수(첫번째 인자), [](두번째 인자))의 두번째 인자에 들어가는 배열을 "의존성 배열"이라 한다.
의존성 배열(Dependancy Array)
의존성 배열은 useEffect() 함수가 실행되는 조건이 되는 배열을 말한다. 이러한 의존성 배열이 필요한 이유는 useEffect 또한 함수이기 때문에 컴포넌트가 변경될 때마다 실행되기 때문이다.
즉, useEffect 함수의 이벤트를 핸들링하지 않고 컴포넌트 내부의 다른 요소 혹은 하위 컴포넌트가 변경될때마다 useEffect가 실행되는 것이다.
위의 코드에서는 빈 배열만을 의존성 배열로 뒀기 때문에, 처음 실행될 때만 날씨를 받아오게 된다.
하지만 의존성 배열 내부에 상태 변경 함수를 둬서, 일정한 이벤트가 발생할 때마다 날씨를 받아오도록 설정할수도 있다.
이에 관한 예시코드는 다음과 같다.
import React, { useState, useEffect } from "react";
import axios from "axios";
function Weather() {
const [firstWeather, setFirstWeather] = useState(null);
const [secondWeather, setSecondWeather] = useState(null);
useEffect(() => {
axios.get("api/weather/Jeju/2023-02-13")
.then(response => {
setFirstWeather(response.data);
});
}, []); // 첫 번째 날씨를 받아올 때만 실행됨
useEffect(() => {
const getWeather =() => {
axios.get("api/weather/Jeju/2023-02-14")
.then(res => {
setSecondWeather(res.data);
}
});
}, [firstWeather]); // 첫 번째 날씨가 변경될 때마다 실행됨
// 날씨 정보를 화면에 렌더링하는 코드
return (
<div>
<p>First Weather: {firstWeather}</p>
<p>Second Weather: {secondWeather}</p>
<button onClick={getWeather}>날씨 업데이트</button>
</div>
);
}
export default Weather;
'프레임워크&라이브러리 > React.js' 카테고리의 다른 글
State Lifting Up(상태 끌어올리기) (0) | 2023.02.21 |
---|---|
Styled Component (0) | 2023.02.20 |
States & Props (feat. eventHandler) (0) | 2023.02.06 |
Component (0) | 2023.02.02 |
JSX (0) | 2023.01.31 |