import React, { Component } from 'react';
// class App extends React.Component {
// render() {
// return (
// <div>Hello React</div>
// )
// }
// }
const App = () => {
return (
<div>Hello React</div>
)
}
export default App;
함수형 컴포넌트는 리액트가 처음 발표될 당시부터 존재했습니다
하지만 당시에는 함수형 컴포넌트에서는 상태를 관리할 수 없었기 때문에
클래스 컴포넌트의 보조적인 역할로 사용되는데 그쳤습니다
그런데 리액트 버전 16.8버전부터 Hook이라는 기능이 추가되면서,
함수형 컴포넌트에서도 상태를 관리하고, 생명주기 메서드를 사용할 수 있게 되었습니다
코드의 간결함과 직관성 측면에서 함수형 컴포넌트가 지닌 장점이 크기 때문에
최근의 개발 트렌드에서 클래스 컴포넌트는 점차 외면받는 추세라고 합니다
리액트에서도 함수형 컴포넌트 사용을 권장하고 있구요
클래스 문법이 복잡하기도 하지만 무엇보다 this
를 신경 쓸 필요가 없다는 것이
함수형 컴포넌트가 더 사랑받는 가장 큰 이유가 아닐까 싶네요
const [<상태값 저장 변수>, <상태값 갱신 함수>] = useState(<상태 초기값>)
// 구조분해할당으로 꺼내 쓸 수 있습니다
import React, { useState } from "react"
const [a, b] = useState(false)
// - a : 상태의 초기값입니다 (useState의 인자, 즉 false입니다)
// - b : 상태 값을 업데이트하는 함수입니다
useState
는 함수형 컴포넌트에서 상태 관리를 가능하게 만드는 함수입니다
(리턴값은 배열입니다)
↓ 예제 코드
import React, { useState } from "react"
const LoginBox = () => {
// state = { isLogin: true }
const [isLogin, setIsLogin] = useState(false)
return (
<div>
<button onClick={() => setIsLogin(!isLogin)}>{isLogin ? "로그아웃" : "로그인"}</button>
</div>
)
}
export default LoginBox
클래스 컴포넌트를 사용할 때보다 코드가 훨씬 간결해졌습니다
useEffect()
는 함수형 컴포넌트에서 상태를 추적하기 위한 함수입니다
(생명주기 메서드와 비슷한 역할을 합니다)
import React, { useState, useEffect } from "react"
// = componentDidMount
useEffect(()=> {
console.log("hello world1")
}, [])
console.log("hello world2")
코드 실행결과 아래의 hello world2
가 먼저 찍히는 것을 확인할 수 있습니다
그 이유는 위 useEffect
함수가 componentDidMount
와 마찬가지로
처음 컴포넌트가 렌더링되었을 때 호출되기 때문입니다
(위와 같이 함수의 두 번째 인자가 빈 배열일 경우)
만약 특정 요소의 상태를 추적(componentDidUpdate
)하고 싶다면
두번째 인자인 배열안에 상태를 추적할 코드를 지정해야 합니다
useEffect(()=> {
console.log(isLogin)
}, [isLogin])
// false, true, false...
위와 같이 배열 안에 상태나 props 등의 값이 포함되어 있으면,
해당 값이 변경될 때마다 useEffect()
함수가 재실행됩니다
이 때는 useEffect()
가 클래스 컴포넌트의componentDidUpdate()
와 같은 역할을 수행합니다
↓ 정리
// = componentDidMount
useEffect(()=> {
console.log("ComponentDidMount")
}, [])
// = componentDidUpdate
useEffect(()=> {
console.log("ComponentDidUpdate")
}, [isLogin])
console.log("Component 재실행")
// Component 재실행
// ComponentDidMount
// ComponentDidUpdate
// Component 재실행
// ComponentDidUpdate
// Component 재실행
// ...
다만 함수형 컴포넌트에서 this를 신경쓸 필요가 없다는 점이 반드시 장점인 것은 아닙니다
상태가 바뀔 때마다 render()
함수만 재호출되는 클래스형 컴포넌트와 달리,
함수형 컴포넌트에서는 위와 같이 상태로 인한 구분점이 없는 함수 안의 모든 코드들이 재실행됩니다
import React, { useState } from "react"
const Counter = () => {
const [count, setCount] = useState(0)
const increment = () => {
setCount(count + 1)
}
const decrement = () => {
setCount(count - 1)
}
return (
<div>
<h1>Counter : {count}</h1>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
)
}
export default Counter
useState()
사용법에 빨리 익숙해집시다
코드에 대한 추가적인 설명은 생략
Axios 설치
npm install axios
Dog API
https://dog.ceo/api/breeds/image/random
*랜덤으로 강아지 이미지를 출력해주는 API입니다
// https://dog.ceo/api/breeds/image/random
import React, { useState, useEffect } from "react"
import axios from "axios"
const Dog = () => {
const [loading, setLoading] = useState(true)
const [dog, setDog] = useState("")
const getDogImage = async () => {
setLoading(true)
const response = await axios.get("https://dog.ceo/api/breeds/image/random")
setDog(response.data.message)
setLoading(false)
}
useEffect(() => {
getDogImage()
}, [])
// getDogImage에서 setLoading이 두 번 실행되기 때문에 아래 콘솔도 두번씩 찍힙니다
console.log("component 재실행")
return (
<div>
{
loading
? "Loading..."
: <img src={dog} alt="" />
}
// 응답 데이터를 받는 동안에는 버튼을 비활성화시킵니다
<button onClick={getDogImage} disabled={loading && "disabled"}>새로고침</button>
</div>
)
}
export default Dog
비동기 요청을 할 때는 주로 isLoading과 같은 상태를 추가하고
응답을 받는 중에는 이벤트를 막아두는 것을 추천합니다
useEffect()
는 프로미스 객체를 반환받을 수 없기 때문에
함수 외부에 비동기 함수를 따로 만들 필요가 있습니다
오늘은 여기까지..