리액트에서 Hook은 함수형 컴포넌트에서 React State와 생명주기 기능을 연동할 수 있게 해주는 함수이다.
Hook은 class안에서는 동작하지 않으며, class 없이 React를 사용할 수 있게 한다.
- 클래스형과 함께 사용할 수도 있다.
- Hook이 기존의 React 컨셉을 대체하는 것이 아니다. 대신에, Hook은 props, state, context, refs, 그리고 lifecycle와 같은 React 개념에 좀 더 직관적인 API를 제공한다.
- 기존의 라이프사이클 메서드 기반(wrapper hell)이 아닌, 로직 기반으로 나눌 수 있어서 컴포넌트를
함수 단위로 잘게 쪼갤 수 있다
는 장점 - 라이프사이클 메서드에는 관련 없는 로직이 자주 섞여 들여가는데, 이로 인해 버그가 쉽게 발생하고 무결성이 깨질 수 있다.
- ❌ 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 안된다. ❌
- 이 규칙을 따르면 컴포넌트가 렌더링될 때마다 항상 동일한 순서로 Hook이 호출 되는 것을 보장한다.
- ❌ 일반 JS 함수에서는 Hook을 호출해서는 안된다. ❌
가장 기본적인 빌트인 Hook으로서, 함수형 컴포넌트에서도 가변적인 상태를 지니고 있을 수 있게 해준다. 함수형 컴포넌트에서 상태를 관리해야할 때 사용
import React, { useState } from 'react';
const Counter = () => {
const [value, setValue] = useState(0);
return (
<div>
<p>
현재 카운터 값은 <b>{value}</b> 입니다.
</p>
<button onClick={() => setValue(value + 1)}>+1</button>
<button onClick={() => setValue(value - 1)}>-1</button>
</div>
);
};
const [value, setValue] = useState(0); 배열 비구조화 할당문법이다. 함수 파라미터로 0이라는 기본값을 넣어준 것 상태값이 바뀌면 컴포넌트는 리랜더링 된다. 기본 값은 어떤 값도 들어갈 수 있다.(객체가 들어갈 수도 있음)
setState의 동작 원리
- state가 바뀌면 화면 전체가 자동으로 다시 그려진다. (리렌더링)
- setState는 비동기로 작동한다. = state의 값은 setState가 호출되는 시점이 아닌, 해당 코드가 들어있는 함수가 모두 실행된 이후에 바뀐다.
💡 왜??? 💡
setState가 비동기가 아닌 동기로 작동하게 되면 변경될 때마다 바로바로 렌더링을 하기 때문에 비효율적이다.
await s3.upload(params, async (err: any, data: any) => {
if (err) {
alert('시스템 에러, 관리자에게 문의하세요.');
setIsLoading(false);
console.log("err", err);
return;
} else {
try{
await axios.post("https://idog.store/blockchain/uploadIpfs", {
img: data.Location,
petName: petName,
petSpecies: petSpecies,
petBirth: petBirth,
petGender: petGender,
}).then(async (data) => {
const nftCid = data.data.nftCid;
const imageOrigin = "https://ipfs.io/ipfs/" + data.data.imageCid;
console.log("nftCid", nftCid);
const overrides = {
gasPrice: ethers.parseUnits('9000', 'gwei') // gasPrice 설정 (예: 100 gwei)
};
const walletAddress = myWalletAddress;
console.log("walletAddress", walletAddress);
if (data.status=== 200) {
const tx = await mintDogTokenContract.mintDogProfile(
walletAddress,
`ipfs://${nftCid}`
);
...
리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hook.
Mount, Update, Unmount 가 합쳐진 형태라고 생각해도 된다.
❗️만약 화면을 다 그리기 이전에 동기화 되어야 하는 경우에는,useLayoutEffect를 활용하여 컴포넌트 렌더링 - useLayoutEffect 실행 - 화면 업데이트 순으로 effect를 실행시킬 수 있다.
useEffect(() => {}); // 렌더링 결과가 실제 돔에 반영된 후마다 호출
만약 useEffect 에서 설정한 함수가 컴포넌트가 화면에 가장 처음 렌더링 될 때
만 실행되고 업데이트 할 경우에는 실행 할 필요가 없는 경우엔 함수의 두번째 파라미터에 빈 배열[]을 넣는다.
useEffect(() => {
console.log('마운트 될 때만 실행됩니다.');
}, []);
useEffect 의 두번째 파라미터로 전달되는 배열 안에 검사하고 싶은 값을 넣어준다.
useEffect(() => {
console.log(name);
}, [name]);
- 메모리 누수 방지를 위해 UI에서 컴포넌트를 제거하기 전에 수행
- 컴포넌트가 여러 번 렌더링 된다면 다음 effect가 수행되기 전에 이전 effect가 정리된다.