리렌더링을 위해 컴포넌트 내부 값의 변경을 도와주는 React Hook
// 기존 업데이트 방법
setState(number + 1);
// 함수형 업데이트 방법
setState(() => {});
기존 업데이트 방법
함수형 업데이트
컴포넌트가 렌더링 될 때마다 특정한 작업을 수행하도록 설정할 때 사용하는 Hook
import React, { useEffect } from "react"
useEffect(() => {
// 실행할 함수
console.log("hello");
}, [ ]); // 의존성 배열
import React, { useEffect } from "react";
const App = () => {
useEffect(() => {
// 화면에 컴포넌트가 나타났을 때
// mount될 때 실행하고자 하는 함수
return () => {
// 화면에서 컴포넌트가 사라졌을 때
// umount될 때 실행하고자 하는 함수
}
}, [])
return <div>Hello world!</div>
}
DOM 요소에 접근할 수 있도록 하는 React Hook
특정 DOM 요소를 선택하기 위해 사용한다.
import React, { useRef } from "react";
const ref = useRef("초기값");
console.log("ref", ref);
ref.current = "변경값"; // 변경
console.log("ref", ref);
function App() {
// state 초기 세팅
const [count, setCount] = useState(0);
// ref 초기 세팅
const countRef = useRef(0);
// useState 사용
const plusStateCountButtonHandler = () => {
setCount(count + 1);
};
// useRef 사용
const plusRefCountButtonHandler = () => {
countRef.current++;
console.log(countRef.current);
};
const styled = { border: "1px solid black", margin: "10px", padding: "10px" };
return (
<>
<div style={styled}>
state 영역입니다. {count} <br />
<button onClick={plusStateCountButtonHandler}>state 증가</button>
</div>
<div style={styled}>
ref 영역입니다. {countRef.current} <br />
<button onClick={plusRefCountButtonHandler}>ref 증가</button>
</div>
</>
);
}
useState
를 사용할 경우 setState가 실행될 때 리렌더링이 발생하기 떄문에 바로 화면에 반영 되지만 useRef
를 사용할 경우 렌더링이 일어나지 않기 때문에 화면에 바뀐 값이 반영되지 않는다.
useRef
의 경우 console.log
로 값을 확인해봤을 때는 값이 변경되지만 화면에는 반영되지 않는 것을 알 수 있다.
state는 리렌더링이 꼭 필요할 값을 다룰 때 사용하고,
ref는 리렌더링을 발생시키지 않는 값을 저장할 때 사용한다.
import React, { useEffect, useRef } from "react";
function App() {
const idRef = useRef("");
useEffect(() => {
idRef.current.focus(); // input에 설정된포커싱
}, []);
return (
<>
<div>
아이디 : <input type="text" ref={idRef} />
</div>
<div>
비밀번호 : <input type="password" />
</div>
</>
);
}
export default App;
import React, { useEffect, useRef, useState } from "react";
function App() {
const [id, setId] = useState("");
const idRef = useRef("");
const pwRef = useRef("");
useEffect(() => {
idRef.current.focus();
}, []);
// id값이 바뀔 때마다 실행
useEffect(() => {
if (id.length >= 10) { // id값이 10자리를 넘을 경우
pwRef.current.focus(); // pw에 포커싱
}
}, [id]);
const handleId = (e) => {
setId(e.target.value);
};
return (
<>
<div>
아이디 :{" "}
<input type="text" ref={idRef} value={id} onChange={handleId} />
</div>
<div>
비밀번호 : <input type="password" ref={pwRef} />
</div>
</>
);
}
export default App;
prop drilling의 문제점
이러한 문제점을 해결하기 위해 react context API를 사용할 수 있다.
useContext hook를 통해 우리는 전역 데이터를 관리할 수 있다
createContext
: context 생성Provider
: context 전달(to 하위 컴포넌트)Consumer
: context 변화 감지1) createContext import
// context/FamilyContext.js
import { createContext } from "react";
export const FamilyContext = createContext(null);
2) 값을 내려줄 상위 컴포넌트에서 provider 지정
import React from "react";
import { FamilyContext } from "../context/FamilyContext";
import Father from "./Father";
function GrandFather() {
const houseName = "Kim";
const poketMoney = 10000;
return (
<FamilyContext.Provider // provider로 값을 내려준다.
value={{
houseName,
poketMoney,
}}
>
<Father />
</FamilyContext.Provider>
);
}
export default GrandFather;
3) 값을 받을 컴포넌트에서 useContext로 값 가져오기
import React, { useContext } from "react";
import { FamilyContext } from "../context/FamilyContext";
function Child() {
const data = useContext(FamilyContext); // 값 가져오기
console.log("data", data);
return (
<div>
<p>집 이름 : {data.houseName}</p>
<p>용돈 : {data.poketMoney}</p>
</div>
);
}
export default Child;
(1) useState를 다시 복습하면서 useState로 기본적인 배치 업데이트를 할 경우 같은 명령을 실행할 때 한번만 실행되며, 순차적으로 모든 명령을 실행하기 위해선 setState(() => {})
와 같이 함수형 업데이트를 사용한다는 것을 알게 되었다.
(2) useEffect는 컴포넌트가 렌더링 될 때마다 특정한 작업을 수행할 수 있도록 도와주는 Hook인데 첫번째 인자에 실행할 함수를 작성하고 두번째 인자엔 의존성 배열을 넣는다. 의존성 배열이 빈값일 경우 처음 렌더링 될 때 딱 한번만 실행되고, 값을 지정해주었을 땐 값이 변경될 때마다 렌더링 된다.
이런 특징으로 불필요한 리렌더링을 하지 않고 싶을 때나 특정 값이 변경될 때마다 함수를 실행하고 싶을 때 useEffect를 유용하게 사용할 수 있을 것 같다.
useEffect에서는 마운트될 때 실행하고자 함수를 지정할 수 있을 뿐만 아니라, 언마운트될 때 실행하고자 하는 함수를 return () => {} 안에 작성해서 지정할 수 있는데 이것을 clean up이라고 한다. 화면에 나타날 때와 사라질 때 함수를 각각 지정하기 위해 사용할 수 있다.
(3) useRef는 DOM 요소에 접근할 수 있도록 하는 Hook로써 vanila JS에서 돔을 제어하는 방식과 비슷하게 특정 DOM 요소를 선택하기 위해 사용된다. 기본적으로 저장공간으로써 사용하는데 이때 ref에 저장한 값은 state를 사용할 때와 다르게 렌더링을 일으키지 않기 때문에 ref 값에 변화가 일어나도 렌더링이 되지 않는다.
즉, ref 값에 변화가 일어나도 내부 변수들이 초기화 되는 것을 막기 때문에 컴포넌트가 계속 렌더링 되어도 언마운트 전까지 값을 유지할 수 있도록 한다. 이러한 특성 때문에 리렌더링이 꼭 필요한 값을 다룰 땐(화면에 반영할 값) state를 사용하고, 리렌더링을 발생시키지 않는 값을 저장할 땐 ref를 사용한다.
(4) useContext는 prop drilling의 문제점(prop의 출처 확인 어려움, 오류 발생시 추적의 어려움)을 해결하기 위한 hook이다. useContext를 통해 context API인 createContext, Provider, consumer을 사용하여 전역 데이터를 좀 더 편리하게 관리할 수 있다.