์ฐธ์กฐ: https://ko.reactjs.org/docs/hooks-reference.html#useref
useRef๋ ์๊ฐ๋ณด๋ค ์ ์ฉํฉ๋๋ค. SPA์์๋ ๋ณํ์ ๋ฐ๋ฅธ ๋ ๋๋ง์ผ๋ก ๊ฐ์ฒด์ ์ง์ ์ ๊ทผํ๋ ๊ฒ์ ์ํํฉ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ React์์๋ useRef hook์ ์ง์ํฉ๋๋ค. useRef๊ฐ ์ง์ ๊ฐ์ฒด์ ์ ๊ทผํ๋ ๊ฒ์ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ ์ด์ ๋ ๋งค๋ฒ ๋ ๋๋ง์ ํ ๋๋ง๋ค ๋์ผํ ๊ฐ์ฒด๋ฅผ ์ ๊ณตํ๋ค๊ณ ๊ณต์๋ฌธ์์ ๋์์์ต๋๋ค.
๋ฐ๋ฉด, state์๋ ๋ฌ๋ฆฌ ์ค์๊ฐ ๋ณํ๋ฅผ ๊ฐ์งํ์ฌ ๋ณํ๋ ๊ฐ์ ๋ฆฌํดํ์ง๋ ์์ต๋๋ค.
์ด๊ฒ ๊ฐ๋ฅํ๊ฒ ํ๋ ค๋ฉด ref๋ฅผ ๋ฐ๋ก setStateํด์ค์ผ ํฉ๋๋ค.
1. useRef๋ฅผ ํตํ timer๋ง๋ค๊ธฐ
์ฐธ์กฐ : https://dmitripavlutin.com/react-useref-guide/
ํ์ด๋จธ๋ฅผ ๋ง๋ค๊ธฐ ์ํ jsx๋ฅผ ์์ฑํฉ๋๋ค.
import { useState, useRef } from "react";
export default function UseRefSample1() {
const countRef = useRef(null);
const [Count, setCount] = useState(0);
return (
<div className="wrap">
<h2>StopWatch ๋ง๋ค๊ธฐ</h2>
<div>
<div className="timer">Timer: {Count}ms</div>
<button>Start</button>
<button>Stop</button>
<button>Reset</button>
</div>
</div>
);
}
countRef๋ setInterval์ ๋ด๊ธฐ ์ํจ์ด๊ณ Count state๋ ์ด ๋จ์๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ํ์ด๋จธ ์์, ์ค์ง, ๋ฆฌ์ ๊ธฐ๋ฅ์ ๊ตฌํํฉ๋๋ค.
const startHandler = () => {
countRef.current = setInterval(() => setCount((c) => c + 1), 100);
};
const stopHandler = () => {
clearInterval(countRef.current);
countRef.current = null;
};
const resetHandler = () => {
stopHandler();
setCount(0);
};
startHandler์์ setInterval๋ก ์ด๋จ์ Count์ setState ์์ผ์ฃผ๊ณ ํด๋น setInterval์ ref.current์ ๋ด๊ฒจ์์ต๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ stopHandler์์ ์ฝ๊ฒ clearInterval์ ํด์ค ์ ์์ต๋๋ค.
๋ค์ startHandler๋ฅผ ํด๋ฆญํ๋ฉด Count์ ๊ฐ์ ๋จ์์์ผ๋ฏ๋ก ๊ธฐ์กด ์นด์ดํธ๊ฐ ์์ธ ๊ฐ์์ ๋ค์ 1์ด๋ง๋ค ํ๋ฌ์ค๋๊ณ ,
resetHandler์์ ์จ์ ํ ๋ฆฌ์ ์ ์ํด Count์ ๊ฐ๋ 0 ์ฒ๋ฆฌํด์ค๋๋ค.
2. useRef๋ฅผ ํตํด input Focus ์ฃผ๊ธฐ
ํ๋ก์ ํธ์ ์ ๋ ฅํ๋ form ์์์ ๋น ๊ฐ ์ฒดํฌ๋ฅผ ํด์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค๋ฉด ์ฒดํฌ ํ ํด๋น input์ผ๋ก focus๋ฅผ ์ฃผ๋ ๊ธฐ๋ฅ์์ ์ ์ฉํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
์ฐ์ ๋งํฌ์ ์ ํด์ค๋๋ค.
import { useEffect, useRef, useState } from "react";
export default function UseRefSample2() {
const [Msg, setMsg] = useState(null);
return (
<div className="wrap">
<h2>Input Focus</h2>
<p>
<input placeholder="Name" />
</p>
<p>
<input placeholder="Age" />
</p>
<button>Submit</button>
{
Msg === null ? ""
: Msg ? <div className="msg">๋ชจ๋ ์
๋ ฅ๋์์ต๋๋ค!</div>
: <div className="msg warning">๋ชจ๋ ์
๋ ฅํ์ธ์!</div>
}
</div>
);
}
๊ทธ๋ฆฌ๊ณ input value์ state๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค. ์ ๋ ฅ ์์์ด ์ฌ๋ฌ ๊ฐ๋ผ๋ฉด ๊ฐ์ฒด ํ์ ์ผ๋ก ํ state์ ๋ฌถ๊ณ name๊ฐ์ ํค๊ฐ์ผ๋ก ์ง์ ํ์ฌ onChange์ ์ํ ๋ณ๊ฒฝํด์ฃผ๋ ๊ฒ์ ์ถ์ฒํฉ๋๋ค.
{...}
const [Inputs, setInputs] = useState({
name: "",
age: ""
});
const handleChange = (e) => {
setInputs({
...Inputs,
[e.target.name]: e.target.value
});
};
{...}
<p>
<input
placeholder="Name"
name="name"
value={Inputs.name}
onChange={handleChange}
/>
</p>
<p>
<input
placeholder="Age"
name="age"
value={Inputs.age}
onChange={handleChange}
/>
</p>
๊ทธ๋ฆฌ๊ณ ๋ชจ๋ ์ ๋ ฅํ ๋ค ์ฒ๋ฆฌ๋๋ handleSubmit์ ์์ฑํฉ๋๋ค.
์ฌ๊ธฐ์๋ ๊ฐ๋จํ๊ฒ Msg ๊ฐ ํ๋๋ฅผ ๋์ด null์ผ ๋๋ ๋ฉ์์ง๊ฐ ๋ณด์ด์ง ์๊ณ , false์ผ ๋๋ "๋ชจ๋ ์ ๋ ฅํ์ธ์!", true์ผ ๋๋ "๋ชจ๋ ์ ๋ ฅ๋์์ต๋๋ค."๋ผ๋ ๋ฉ์์ง๋ฅผ ๋์๋๋ค.
์ด๋ ๋น ๊ฐ ์ฒดํฌ๋ฅผ ํ๊ฒ ๋๋๋ฐ handleCheckForm ํจ์๋ฅผ ๋ฐ๋ก ๋์ด ์ฌ์ฉํ๋๋ก ํ๊ฒ ์ต๋๋ค.
const handleSubmit = (e) => {
if (handleCheckForm()) {
setMsg(true);
} else {
setMsg(false);
}
};
const handleCheckForm = () => {
if (Inputs.name === "") {
alert("์ด๋ฆ์ ์
๋ ฅํ์ธ์!");
return false;
}
if (Inputs.age === "") {
alert("๋์ด๋ฅผ ์
๋ ฅํ์ธ์!");
return false;
}
return true;
};
return (
<div className="wrap">
<h2>Input Focus</h2>
{ ... }
<button onClick={handleSubmit}>Submit</button>
{Msg === null ? (
""
) : Msg ? (
<div className="msg">๋ชจ๋ ์
๋ ฅ๋์์ต๋๋ค.</div>
) : (
<div className="msg warning">๋ชจ๋ ์
๋ ฅํ์ธ์!</div>
)}
</div>
);
name, age ๋ ์ค ํ๋๋ผ๋ ๋น ๊ฐ์ด๋ฉด false๋ฅผ ๋ฐํํ๊ณ ๋ ๋ค ๋น๊ฐ์ด ์๋๋ฉด true๋ฅผ ๋ฐํํ๋ฉด์ setMsg๊ฐ true ํน์ false๋ก ๋ณ๊ฒฝ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ฉด ๋๋จธ์ง ๋ถ๊ฐ ๊ธฐ๋ฅ๋ค์ useRef๋ฅผ ํตํด ์ฒ๋ฆฌํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
1. submitํด๋ฆญ ์ ๊ฐ์ด ๋น์ด์๋ input์ ์๋ focus๋ฅผ ํ๋ค.
2. name input์์ Enter์ ๋ค์ input์ผ๋ก ์ด๋, age input์์ Enter์ handleSubmit ํธ์ถ
๋จผ์ useRef๋ฅผ ํตํด nameRef, ageRef๋ฅผ ์ ์ธํ๊ณ input์ ์ฐ๊ฒฐ์์ผ์ค๋๋ค.
๊ฐ์ฒด ์ ๊ทผ์ current๋ฅผ ํตํด ํ ์ ์์ต๋๋ค.
ํด๋น ref๋ฅผ console๋ก ์กฐํํด๋ณด๋ฉด ๋ด๋ถ์ ์ผ๋ก ๋ง์ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์์ ์ ์ ์์ต๋๋ค.
import { useEffect, useRef, useState } from "react";
const nameRef = useRef(null);
const ageRef = useRef(null);
// Enter์ age input์ผ๋ก focus
const handleNextInput = (e) => {
if (e.key === "Enter") {
ageRef.current.focus();
}
};
// Enter์ handleSubmit ํธ์ถ
const handleChangeSubmit = (e) => {
if (e.key === "Enter") handleSubmit();
};
// ์ต์ด ํ์ด์ง ์ง์
์ name input์ focus
useEffect(() => {
nameRef.current.focus();
}, []);
{...}
<p>
<input
placeholder="Name"
name="name"
value={Inputs.name}
ref={nameRef}
onChange={handleChange}
onKeyPress={handleNextInput}
/>
</p>
<p>
<input
placeholder="Age"
name="age"
value={Inputs.age}
ref={ageRef}
onChange={handleChange}
onKeyPress={handleChangeSubmit}
/>
</p>
์ด ์ธ์ useRef๋ฅผ ํตํด ๋ค๋ฅธ ๊ธฐ๋ฅ์ ๊ตฌํํ ๊ฒ๋ค์ ์ดํด๋ณด๊ณ ์ถ๋ค๋ฉด ํด๋น ๊ธ๋ ํ์ธํด๋ณด์ธ์.
React div ์คํฌ๋กค์ Fix ํ๊ธฐ (Element scroll)
React ์์ ์ ๋๋ฉ์ด์ , ์ธํฐ๋ ์ ๊ตฌ์ถํ๊ธฐ (emotion / tweenmax)
'๊ฐ๋ฐ ๐พ > ReactJS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Toast ํ์ ๋ง๋ค๊ธฐ (0) | 2021.07.06 |
---|---|
์ด๊ฐ๋จ useContext + useReducer (0) | 2021.07.02 |
React ์์ ์ ๋๋ฉ์ด์ , ์ธํฐ๋ ์ ๊ตฌ์ถํ๊ธฐ (emotion / tweenmax) (0) | 2021.06.23 |
react draggable ๊ฐ๋จ ์ํ (0) | 2021.06.22 |
๋ฆฌ์กํธ์์ setInterval์ ์ฌ์ฉํ์ฌ ํ์ดํ ํจ๊ณผ ์ฃผ๊ธฐ (0) | 2021.06.18 |