useRef() VS useState()
useState()
: 화면을 업데이트해야하는 '상태'를 저장하는 용도
-> 상태가 바뀌면 화면이 다시 렌더링된다
VS
useRef()
: 리렌더링 없이 값을 저장하거나 DOM에 접근하는 용도
-> 값이 바뀌어도 화면이 렌더링되지 않는다
- 값이 바뀌어도 화면을 바꾸고 싶지 않을 때 사용
- useState()를 남발하면 불필요한 렌더가 계속 일어나기 때문에 성능이 저하된다
-> useRef()가 훨씬 효율적이 될 수 있다
- checkBox처럼 화면과 무관한 값을 저장할 때 useRef()를 사용하기 좋다
Check 유효성 검사
| 사용자로부터 ID와 PW를 입력받아 전송 유효성 검사를 통해 ID와 PW과 입력받지 않은 경우 경고창을 띄운다 |
import React from 'react';
import { useRef } from 'react';
// 아이디, 비밀번호를 눌렀을 때 유효성 검사
// 순서가 상관이 없어서 배열이다 ->
// ** 객체는 순서대로 value값이 들어가야 함
const Check = () => {
const expressionRef = useRef([])
const formRef = useRef()
const handleSubmitOnClick = () => {
for(let input of expressionRef.current){
if(!input.value){
console.error(`${input.name}의 값이 없습니다.`)
alert(`${input.name} 정보를 입력하세요`)
return;
}
}
// 데이터 전송
formRef.current.submit()
}
return (
<div>
<form action="" ref={formRef}>
<span>ID</span>
<div><input ref={(el) => expressionRef.current[0] = el} type="text" name="id" /></div>
<span>PW</span>
<div><input ref={(el) => expressionRef.current[1] = el} type="text" name="pw" /></div>
<button type="button" onClick={handleSubmitOnClick}>GO!</button>
</form>
</div>
);
};
export default Check;
- ref={(el) => expressionRef.current[0] = el}
- [] 배열 사용: 순서 상관 없이 한꺼번에 물어봄
-> 앞/뒤 순서 상관 없이 질문에 대한 답만 받으면 됨
- 콜백함수 사용: 앞에서 값을 받아서 자기의 태그를 그대로 주는 함수
<결과화면>


- ID와 PW를 모두 입력한 후 GO!버튼을 누르면 정상적으로 전송됨
CheckBoxRef
import React from 'react';
import { useRef, useState } from 'react';
const CheckBoxRef = () => {
const [hobbies, setHobbies] = useState("");
const inputRef = useRef([])
const handleHobbiesOnClick = () => {
const hobby = inputRef.current
.filter((checkbox) => checkbox.checked)
.map((checkbox) => checkbox.value)
.join(", ")
setHobbies(hobby)
}
return (
<div>
<div>
<label><span>Running</span>
<input type="checkbox" value="Running" name="hobby"
ref={(el) => inputRef.current[0] = el}
/>
</label>
<label><span>Reading books</span>
<input type="checkbox" value="Reading books" name="hobby"
ref={(el) => inputRef.current[1] = el}
/>
</label>
<label><span>Belly Dancing</span>
<input type="checkbox" value="Belly Dancing" name="hobby"
ref={(el) => inputRef.current[2] = el}
/>
</label>
<button onClick={handleHobbiesOnClick} type="button">CLICK</button>
</div>
<p>{hobbies}</p>
</div>
);
};
export default CheckBoxRef;
<결과화면>

- 체크박스에 체크한 후 CLICK 버튼을 누르면
아래쪽에 체크한 항목이 출력된다
- 다시 체크를 해제하고 버튼을 누르면 그대로 반영된다
CheckBoxRef2
| 사용자가 체크박스를 클릭하면 체크한 취미를 화면에 실시간으로 보여준다 사용자가 체크박스를 해제하면 체크한 취미도 화면에서 사라진다. |
import { useRef, useState } from 'react';
const CheckBoxRef02 = () => {
const [hobbies, setHobbies] = useState("");
const inputRef = useRef([])
const handleHobbiesOnChange = () => {
const hobby = inputRef.current
.filter((checkbox) => checkbox.checked)
.map((checkbox) => checkbox.value)
.join(", ")
setHobbies(hobby)
}
return (
<div>
<div>
<label>
<span>Running</span>
<input type="checkbox" onChange={handleHobbiesOnChange} value="Running" name="hobby"
ref={(el) => inputRef.current[0] = el}
/>
</label>
<label>
<span>Reading books</span>
<input type="checkbox" onChange={handleHobbiesOnChange} value="Reading books" name="hobby"
ref={(el) => inputRef.current[1] = el}
/>
</label>
<label>
<span>Belly Dancing</span>
<input type="checkbox" onChange={handleHobbiesOnChange} value="Belly Dancing" name="hobby"
ref={(el) => inputRef.current[2] = el}
/>
</label>
</div>
<p>{hobbies}</p>
</div>
);
};
export default CheckBoxRef02;
<결과화면>

- 체크박스의 DOM에서 체크된 값을 읽어와서 value값만 골라 문자열로 합쳐 hobbies state에 넣는다
- 버튼 없이 체크박스를 선택하자마자 곧바로 결과 반영
CheckBoxRef3
| hobbies를 문자열이 아닌 li태그(컴포넌트)로 분리하여 출력 |
<CheckBoxRef03>
import React, { useRef, useState } from "react";
import Hobby from "./Hobby";
const CheckBoxRef03 = () => {
const [hobbies, setHobbies] = useState([]);
const inputRef = useRef([]);
const handleHobbiesOnChange = (e) => {
if(e.target.checked){
setHobbies([...hobbies, e.target.value])
}else{
setHobbies(hobbies.filter((hobby) => hobby !== e.target.value))
}
console.log(hobbies)
}
const hobbyList = hobbies.map((hobby, i) => (
<Hobby key={i} hobby={hobby} />
))
return (
<div>
<div>
<label>
<span>Running</span>
<input type="checkbox" value="Running" name="hobby"
onChange={(e) => handleHobbiesOnChange(e)}
/>
</label>
<label>
<span>Reading Books</span>
<input type="checkbox" value="Reading Books" name="hobby"
onChange={(e) => handleHobbiesOnChange(e)}
/>
</label>
<label>
<span>Belly Dancing</span>
<input type="checkbox" value="Belly Dancing" name="hobby"
onChange={(e) => handleHobbiesOnChange(e)}
/>
</label>
</div>
<ul>
{hobbyList}
</ul>
</div>
);
};
export default CheckBoxRef03;
<Hobby 컴포넌트>
import React from 'react';
const Hobby = ({hobby}) => {
return (
<li>
{hobby}
</li>
);
};
export default Hobby;
- 컴포넌트는 함수 단위로 분리하며, 확장성을 고려한 것
- 아이콘, 하이라이트, 상세정보 등 다양한 기능 및 스타일을 추가할 수 있다
<결과화면>

+
컴포넌트에 다양한 기능을 추가해 확장 가능
<수정된 Hobby 컴포넌트>
import React, { useState } from "react";
const iconMap = {
"Running": "🏃♂️",
"Reading Books": "📚",
"Belly Dancing": "💃",
};
const Hobby = ({ hobby }) => {
const [isHover, setIsHover] = useState(false);
const style = {
padding: "8px 12px",
cursor: "pointer",
listStyle: "none",
display: "flex",
alignItems: "center",
gap: "8px",
borderRadius: "6px",
transition: "0.2s",
backgroundColor: isHover ? "#f0f0f0" : "white",
color: isHover ? "#0077ff" : "#333",
fontSize: "15px"
};
return (
<li
style={style}
onMouseEnter={() => setIsHover(true)}
onMouseLeave={() => setIsHover(false)}
>
<span>{iconMap[hobby]}</span>
<span>{hobby}</span>
</li>
);
};
export default Hobby;
<결과화면>

FoodContainer
| 사용자가 음식명을 국문/영문으로 입력하고 추가 버튼을 누르면 추가 각 메뉴는 체크박스 형태로 화면에 출력 사용자가 체크박스에 체크해 삭제버튼을 누르면 선택한 항목이 삭제된다 |
<FoodContainer>
import React from 'react';
import { useRef, useState } from "react";
import Food from "./Food";
const FoodContainer = () => {
const inputRef = useRef([]);
const [foods, setFood] = useState([]);
const [checked, setChecked] = useState([]);
const handleAddFoodOnClick = () => {
const kor = inputRef.current[0].value;
const eng = inputRef.current[1].value;
setFood([...foods, { kor, eng }]);
setChecked([...checked, false]);
};
const handleCheckedOnChange = (i) => {
setChecked(checked.map((c, idx) => (idx === i ? !c : c)));
};
const handleDeleteFoodOnClick = () => {
const newFood = foods.filter((_, i) => !checked[i]);
setFood(newFood);
setChecked(Array(newFood.length).fill(false));
};
const foodList = foods.map(({ kor, eng }, i) => (
<Food
key={i}
kor={kor}
eng={eng}
checked={checked[i]}
onChange={() => handleCheckedOnChange(i)}
/>
));
return (
<div>
<input type="text" placeholder="Add menu(Korean)"
ref={(el) => inputRef.current[0] = el} />
<input type="text" placeholder="English menu"
ref={(el) => inputRef.current[1] = el} />
<button onClick={handleAddFoodOnClick}>ADD</button>
<button onClick={handleDeleteFoodOnClick}>DELETE</button>
<ul>
{foodList}
</ul>
</div>
);
};
export default FoodContainer;
<Food 컴포넌트>
import React from 'react';
const Food = ({ kor, eng, checked, onChange }) => {
return (
<li>
<input
type="checkbox"
checked={checked}
onChange={onChange}
/>
{`${kor} (${eng})`}
</li>
);
};
export default Food;
<결과화면>


- 체크박스를 클릭해 메뉴를 선택하고 DELETE버튼으로 메뉴 삭제 가능
https://developernew.tistory.com/431
리액트 React 설치방법 feat. VS Code
React란? React 리액트- 복잡한 사용자 인터페이스(UI)를 쉽게 구축하기 위해 페이스북에서 제작한 자바스크립트 기반의 라이브러리- 싱글 페이지 애플리케이션이나 모바일 애플리케이션 개발에 주
developernew.tistory.com
https://developernew.tistory.com/438
React 리액트 - 레퍼런스(Ref) useRef() vs useState()
useReference useRef란?: 저장공간 또는 DOM요소에 접근하기 위해 사용되는 React Hook- Ref는 reference, 즉 참조를 뜻한다- ref == DOM리액트는 돔을 지양하기 때문에 돔을 사용하는 것을 권장하지 않는다때문
developernew.tistory.com
'Frontend > React' 카테고리의 다른 글
| React 리액트 - 레퍼런스(Ref) (0) | 2025.12.11 |
|---|---|
| React 리액트 - 맵(Map) (0) | 2025.12.10 |
| React 리액트 - 상태(state) (0) | 2025.12.10 |
| React 리액트 - Props 프로퍼티 구동원리 (0) | 2025.12.08 |
| React 리액트 - 변수 표현, 삼항연산자 (0) | 2025.12.07 |