import { useRef } from 'react';
const testRef = useRef(초깃값);
✅ 초깃값 0 - console.log 확인
⚠️
❌ 렌더링 중에는 ref를 작성 또는 쓰거나 읽지 마세요 🤔
EX)
const testRef = useRef(0);
// ❌
testRef.current = 123456789;
return (
<>
<p>❌ - {testRef.current}</p>
</>
)
👇 👇 👇
// 🟢
const testRef = useRef(0);
const [myRef, setMyRef] = useState(0);
// 🟢
useEffect(() => {
// useEffect에서 ref를 읽거나 변경 가능!!
testRef.current = 123456789;
});
const refChange = () => {
// 이벤트 핸들러에서 ref를 읽거나 변경 가능!!
setMyRef(testRef.current)
}
return (
<div>
{/* 읽거나 사용해야 한다면 state를 사용 */}
<p>🟢 - {myRef}</p>
<button type="button" onClick={refChange}>useRef 변경</button>
</div>
)
const [state, setState] = useState(0);
const ref = useRef(0);
let count = 0;
function stateClick() {
setState((prev) => prev + 1);
console.log('state:', state);
}
function refClick() {
ref.current = ref.current + 1;
console.log('ref', ref.current);
}
function letClick() {
count = count + 1;
console.log('let', count);
}
console.log("렌더링 확인!")
return (
<div>
<div>
<p>state 👉 {state}</p>
<p>변경: 렌더링! 변경 값 노출</p>
<button type="button" onClick={stateClick}>state Click</button>
</div>
<hr />
<div>
<p>ref 👉 {ref.current}</p>
<p>변경: 렌더링 되지 않아 변경 값 노출 X, 컴포넌트 렌더링 될 때 반영</p>
<button type="button" onClick={refClick}>ref Click</button>
</div>
<hr />
<div>
<p>let 👉 {count}</p>
<p>변경: 렌더링 X, 렌더링 시 반영 값 X : 초깃값으로 재시작</p>
<button type="button" onClick={letClick}>let Click</button>
</div>
</div>
)
const [time, setTime] = useState(0);
const intervalRef = useRef(null);
function timeStart() {
intervalRef.current = setInterval(() => {
setTime(prev => prev+1);
}, 100);
}
function timeStop() {
clearInterval(intervalRef.current);
}
return (
<>
<p>{time}</p>
<button type="button" onClick={timeStart}>시작</button>
<button type="button" onClick={timeStop}>정지</button>
</>
)
const inputRef = useRef();
const aRef = useRef();
function inputFocus(){
console.log(inputRef.current); // <input type="text">
inputRef.current.focus();
}
function aFocus(){
console.log(aRef.current); // <a href="/">a 태그</a>
aRef.current.focus();
}
return (
<div>
<input
type="text"
ref={inputRef}
/>
<a
href="/"
ref={aRef}
>
a 포커스
</a>
<hr />
<button type="button" onClick={inputFocus}>input focus 이동</button>
<button type="button" onClick={aFocus}>a focus 이동</button>
</div>
)
📍 컴포넌트에 ref prop을 넘겨서 그 내부에 있는 DOM 엘리먼트에 접근을 하게 해주는 forwardRef() 함수.
import { forwardRef } from 'react';
const InputTest = forwardRef(function InputTest(props, ref) {
return <input {...props} ref={ref} />;
});
☝️ 사용 방법
✔️ 부모 컴포넌트에서 Input(자식 컴포넌트) Button 컴포넌트(자식 컴포넌트)를 사용하여 focus 제어.
// 🌟 부모 컴포넌트
import { useRef } from "react";
import RefBtn from "./RefBtn";
import RefInput from "./RefInput";
function RefForwardRef(){
const inputRef = useRef();
return (
<>
<p>📍 자식 RefInput 컴포넌트의 input을 ref 사용하여 접근</p>
<RefInput ref={inputRef} /> {/* 👈 input 접근 */}
<RefBtn focusEl={inputRef}/> {/* ref에 저장된 input으로 focus */}
</>
)
}
export default RefForwardRef;
// 🌟 RefInput.jsx
import { forwardRef } from "react";
function RefInput (props,ref){
return (
<>
<input type="text" ref={ref} />
</>
)
}
export default forwardRef(RefInput); // 👈 forwardRef 사용하여 컴포넌트를 감싸준다.
// 🌟 RefBtn.jsx
function RefBtn({focusEl}){
function focusClcik(){
focusEl.current.focus();
}
return (
<>
<button type="button" onClick={focusClcik}>click</button>
</>
)
}
export default RefBtn;
✅ 정상적으로 포커스 이동이 되는 것을 확인할 수 있습니다.
✍️ 끝.
감사합니다. 😁
참고
🔗 useRef-React