
📅 2025-10-16
➡️ React useState, useEffect, useRef에 대해 새롭게 알게 된 것 또는 헷갈리는 부분 정리
useState는 React의 가장 기본적인 hook이고, 컴포넌트에서 상태를 관리하게 해줌const [state, setState] = useState(initialState);
state를 변수로 사용하고, setState를 이용해서 state값을 수정할 수 있음state가 원시 데이터타입이 아닌 객체 데이터 타입인 경우 불변성을 유지해줘야 함// 일반적인 방식
setCount(count +1);
// 함수형 업데이트
setState((prev) =>{prev + 1});
setState의 ( ) 안에 업데이트 함수 내부에서 수정할 값이 아니라, 함수를 넣을 수 있음state를 가져올 수 있고 { } 안에서는 이 값을 변경하는 코드를 작성하여 업데이트를 할 수 있음배치(batch)function App() {
const [num, setNum] = useState(0);
return (
<div>
<div>{num}</div>
<button
onClick={() => {
setNum(num + 1);
setNum(num + 1);
setNum(num + 1);
}}
>
+ 버튼
</button>
</div>
);
}prev)를 기준으로 새 값을 계산하기 때문에 React가 여러 요청을 순서대로 하나씩 처리function App() {
const [num, setNum] = useState(0);
return (
<div>
<div>{num}</div>
<button
onClick={() => {
setNum((prev) => prev + 1);
setNum((prev) => prev + 1);
setNum((prev) => prev + 1);
}}
>
+ 버튼
</button>
</div>
);
}import React, { useEffect } from "react";
function App() {
useEffect(() => {
console.log("렌더 이후 실행");
});
return <div>Home</div>;
}
export default App;
useEffect(() => {
// 하고 싶은 작업
}, [/* 여기에 의존성 값들 */]);
빈 배열([])인 경우 → 최초 1회
useEffect(() => {
console.log("처음 한 번만 실행");
}, []); // mount 후 1회
값이 있는 경우 → 해당 값이 바뀔 때마다
const [value, setValue] = useState("");
useEffect(() => {
console.log("value 변경 감지:", value);
}, [value]);
value가 바뀔 때마다 effect가 재실행 됨useEffect(() ⇒ {}, [])useEffect(() ⇒ {}, [state])return ( ) ⇒ {…}import React, { useEffect } from "react";
const App = () => {
useEffect(()=>{
// 화면에 컴포넌트가 나타났을(mount) 때 실행하고자 하는 함수 로직
return ()=>{
// 화면에서 컴포넌트가 사라졌을(unmount) 때 실행하고자 하는 함수 로직
}
}, [])
return <div>React App Page</div>
};
export default App;useEffect 안에서 return을 해주고 이 부분에 실행되길 원하는 함수를 넣으면 됨import { useRef } from "react";
const ref = useRef("초기값");
import { useRef } from "react";
function App() {
const boxRef = useRef("초기값"); // { current: "초기값" }
console.log(boxRef);
// 값 변경 (화면은 바뀌지 않음)
boxRef.current = "업데이트된 값";
console.log(boxRef.current); // "업데이트된 값"
return <div>useRef 데모</div>;
}
export default App;

ref 값은 컴포넌트가 몇 번 렌더링되도 unmount 전까지 current를 유지함import { useRef, useState } from "react";
function App() {
const [stateCount, setStateCount] = useState(0);
const refCount = useRef(0);
const incState = () => setStateCount((v) => v + 1);
const incRef = () => {
refCount.current += 1; // 화면엔 즉시 반영되지 않음
console.log("refCount:", refCount.current);
};
return (
<>
<div>
state 카운터: {stateCount}{" "}
<button onClick={incState}>+1 (state)</button>
</div>
<div>
ref 카운터(화면엔 고정): {refCount.current}{" "}
<button onClick={incRef}>+1 (ref)</button>
</div>
</>
);
}
export default App;
stateCount는 바뀌면 리렌더링 됩니다 → 화면이 갱신 됨refCount.current는 값만 바뀝니다 → 화면 갱신 안됨 (로그로만 확인 가능)import { useEffect, useRef } from "react";
function App() {
const idInputRef = useRef(null);
useEffect(() => {
idInputRef.current?.focus(); // 마운트 직후 포커스
}, []);
return (
<>
<div>
아이디: <input type="text" ref={idInputRef} />
</div>
<div>
비밀번호: <input type="password" />
</div>
</>
);
}
export default App; <input /> 태그에는 ref라는 속성이 있습니다. 이것을 이용해서 DOM 요소에 접근할 수 있음import { useEffect, useRef, useState } from 'react';
function App() {
const idRef = useRef(null);
const pwdRef = useRef(null);
const [id, setId] = useState('');
useEffect(() => {
idRef.current?.focus(); // 마운트 직후 포커스
}, []);
useEffect(() => {
if (id.length >= 10) pwdRef.current?.focus();
}, [id]);
const handleLog = (e) => {
setId(e.target.value);
};
return (
<>
<div>
아이디: <input type="text" ref={idRef} value={id} onChange={handleLog} maxLength={10} />
</div>
<div>
비밀번호: <input type="password" ref={pwdRef} />
</div>
</>
);
}
export default App;