개발자의 자기계발 블로그( ੭ ・ᴗ・ )੭
[React] Hook의 개념, 그리고 주요 Hook (UseState, UseEffect) 본문
목차
✅ 리액트 훅 (Hook)
함수형 컴포넌트에서 상태(state)와 생명주기(Lifecycle) 기능을 사용할 수 있게 해주는 기능이다.
원래 있던 기능은 아니고 리액트 16.8에서 도입되었는데,
이를 통해 클래스형 컴포넌트의 필요성을 줄이고 코드의 가독성과 재사용성을 높일 수 있게 되었다.
✅ 주요 훅 소개
1. useState
- 상태 변수를 선언하고 관리하는 훅
- 함수형 컴포넌트 내에서 상태를 사용할 수 있게 해줌
import React, {useState} from "react";
function Counter(){
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick = {() => setCount(count + 1)}>Click me</button>
</div>
);
}
- count는 현재 상태 값을 나타냄
- setCount는 상태 값인 count를 갱신하는 함수
setCount(newCount)를 호출하면 count가 newCount로 업데이트되고 컴포넌트가 다시 렌더링 됨
- useState(0) : 상태의 초기 값을 0으로 설정
2. useEffect
- side effects를 수행할 때 사용하는 훅
- 데이터 가져오기(fetching data), 구독(subscription) 설정, 수종으로 리액트 컴포넌트 업데이트, 타이머 설정 등의 작업을 처리할 수 있음
🔽 예제 1. 의존성 배열이 없는 useEffect 훅 (1)
import './App.css';
import {useState, useEffect} from 'react';
import Timer from './component/Timer';
function App() {
const [count, setCount] = useState(1);
const handleCountUpdate = () => {
setCount(count + 1);
};
// 렌더링 될 때마다 매번 실행
useEffect(() => {
console.log('렌더링!');
})
return (
<div>
<button onClick={handleCountUpdate}>Update</button>
<span>count: {count}</span>
</div>
);
}
export default App;
▶ Update 버튼을 누를 때마다 count가 1씩 증가하면서 콘솔에 '렌더링' 이라는 로그가 매번 찍힘
useEffect 훅에서 두번째 인자. 즉, 의존성 배열이 생략된 경우 컴포넌트가 업데이트 될 때마다 렌더링 되는 것을 확인할 수 있음
🔽 예제 2. 의존성 배열이 없는 useEffect 훅 (2)
import './App.css';
import {useState, useEffect} from 'react';
import Timer from './component/Timer';
function App() {
const [count, setCount] = useState(1);
const [name, setName] = useState('');
const handleCountUpdate = () => {
setCount(count + 1);
};
const handleInputChange = (e) => {
setName(e.target.value);
};
// 렌더링 될 때마다 매번 실행
useEffect(() => {
console.log('렌더링!');
});
return (
<div>
<button onClick={handleCountUpdate}>Update</button>
<span>count: {count}</span><br />
<input type='text' value={name} onChange={handleInputChange}/>
<span>name: {name}</span>
</div>
);
}
export default App;
▶ 마찬가지로 컴포넌트가 업데이트 될 때마다(input박스 안에 글자를 변경할 때마다) 렌더링이 되는 것을 콘솔로 확인할 수 있음 !!
위에 두 예제에서는 컴포넌트가 업데이트 될 때마다 useEffect가 실행되었는데,
그게 아닌 특정한 경우에만 실행시키고 싶은 경우❓❓
🔽 예제 3. 의존성 배열이 있는 useEffect 훅
import './App.css';
import {useState, useEffect} from 'react';
import Timer from './component/Timer';
function App() {
const [count, setCount] = useState(1);
const [name, setName] = useState('');
const handleCountUpdate = () => {
setCount(count + 1);
};
const handleInputChange = (e) => {
setName(e.target.value);
};
// 마운트 될 때 + [ item ] 변경될 때만 실행
useEffect(() => {
console.log('count 변화!');
}, [count]);
return (
<div>
<button onClick={handleCountUpdate}>Update</button>
<span>count: {count}</span><br />
<input type='text' value={name} onChange={handleInputChange}/>
<span>name: {name}</span>
</div>
);
}
export default App;
▶ 예제 2번 코드에서 useEffect() 부분만 바뀜.
두번째 인자로 배열에 count를 넣어줌으로써 count가 변화할 때만 실행되도록 하였다.
input태그에 이름을 입력해도 콘솔이 찍히지 않고 update버튼을 누를 시에만 콘솔이 찍히는 모습을 확인 할 수 있다.
그러면 처음에 마운팅 될 때만 한 번 실행시키고 싶을 땐❓❓
🔽 예제 4. 의존성 배열이 빈 배열일 경우
import './App.css';
import {useState, useEffect} from 'react';
import Timer from './component/Timer';
function App() {
const [count, setCount] = useState(1);
const [name, setName] = useState('');
const handleCountUpdate = () => {
setCount(count + 1);
};
const handleInputChange = (e) => {
setName(e.target.value);
};
// 처음 마운팅 될 때 한 번만 실행
useEffect(() => {
console.log('마운팅 됨!!');
}, []);
return (
<div>
<button onClick={handleCountUpdate}>Update</button>
<span>count: {count}</span><br />
<input type='text' value={name} onChange={handleInputChange}/>
<span>name: {name}</span>
</div>
);
}
export default App;
▶ 처음 마운트 될 때 로그가 찍히고 아무리 count를 update하고, name을 입력해도 아무 변화가 없는 것을 확인할 수 있다.
✅ UseEffect & Clean Up - Timer
clean up 메커니즘은 타이머나 구독(subsciptions) 등을 정리하는 데에 유용하다.
setInterval이나 WebSocker 연결을 정리하는 데 사용할 수 있다.
clean up 기능은 컴포넌트의 성능과 안정성을 유지하는 데 매우 중요한 역할을 함!!
useEffect에서 return 함수 부분이 clean up 함수가 실행될 부분이 된다.
🔽 예제. Timer를 예제로 Clean Up에 대하여 알아보자 !!
App.js
import './App.css';
import {useState, useEffect} from 'react';
import Timer from './component/Timer';
function App() {
const [showTimer, setShowTimer] = useState(false);
return (
<div>
{/*
{<Timer /> && showTimer}로 작성하면 작동 안되는 이유 :
&& 문법은 왼쪽 피연산자가 true일 때만 오른쪽 피연산자를 리턴하는 문법임
*/}
{showTimer && <Timer />}
<button onClick={() => setShowTimer(!showTimer)}>Toggle Timer</button>
</div>
);
}
export default App;
showTimer가 true 일때만 Timer 를 실행
Timer.js
import React, {useEffect} from "react";
const Timer = () =>{
// 타이머 컨포넌트가 화면에 처음 렌더링 될 때만 실행
useEffect(() => {
const timer = setInterval(() => {
console.log('타이머 돌아가는중...')
}, 1000);
return () => {
clearInterval(timer);
console.log('타이머가 종료되었습니다.');
};
}, []);
return (
<div>
<span>타이머를 시작합니다. 콘솔을 보세여</span>
</div>
);
};
export default Timer;
return 함수 내부 내용은 컴포넌트가 언마운트 되기 전에 실행됨
>> 혹시 마운트 하자마자 '타이머가 종료되었습니다' 로그가 찍힌다면???
create-react-app으로 리액트 앱을 만들 시 index.js에 기본적으로 Strict mode가 추가되기 때문이다.
Strict mode는 리액트로 개발할 때 코드 상에 문제점들을 미리 검사하고 콘솔에 알려주는 역할을 하여 한 번 더 실행이 된 것!!
<StrictMode> 태그를 없애주면 해결이 된다❗
⭐ 정리!
포스팅 참고 자료
- 별코딩: React Hooks에 취한다 https://www.youtube.com/playlist?list=PLZ5oZ2KmQEYjwhSxjB_74PoU6pmFzgVMO
React Hooks에 취한다 - 리액트 훅스 쉽게 마스터하기
www.youtube.com
- 인프런 : 처음 만난 리액트 https://inf.run/YehVc
[지금 무료] 처음 만난 리액트(React) | Inje Lee (소플) - 인프런
Inje Lee (소플) | 자바스크립트와 CSS 기초 문법과 함께 리액트의 기초를 탄탄하게 다질 수 있습니다., 깔끔한 강의자료, 꼼꼼한 설명으로쉽게 배우는 리액트 강의입니다. 👨🏫 리액트의 세계로
www.inflearn.com
'JS' 카테고리의 다른 글
[React] 상태(State)와 생명주기(Lifecycle) (0) | 2024.06.19 |
---|---|
[React] Components와 Props (0) | 2024.06.18 |
[React] Rendering Elements (0) | 2024.06.17 |
[React] JSX (0) | 2024.06.17 |
[React] 리액트 시작하기전에 & 소개 (0) | 2024.06.14 |