// 참고, Refs
- DOM 요소에 직접 접근할 때나 UI에 직접적인 영향을 주지 않는 값을 제어할 때 사용한다.
- useRef Hook을 import 해서 사용한다. (https://sorrel012.tistory.com/362 의 useRef 참고)
- useRef로부터 받는 참조 값들은 항상 JavaScript 객체이다.
- HTML 요소에 ref를 통해 참조변수를 설정하면 참조변수명.current를 통해 실제 참조 값을 얻을 수 있다.
<html요소 ref={참조변수명}>
const 변수 = 참조변수명.current.html요소에내장된값 (input의 경우 value)
* input 에 useState()로 value를 사용해서 값을 받아온 후 다른 곳에 사용하려고 한다면 특정 이벤트 발생 시 최종 결과값만 받아올 수 없고 값을 변경할 때마다 받아오게 된다.
ref 를 사용하면 이 문제를 해결할 수 있다!
- ref가 바뀔 때마다 컴포넌트 함수가 재실행되지 않는다.(<-> state)
import { useRef, useState } from 'react';
export default function Player() {
const playerName = useRef();
const [enteredPlayerName, setEnteredPlayerName] = useState(null);
function handleClick() {
setEnteredPlayerName(playerName.current.value);
}
return (
<section id="player">
<h2>Welcome {enteredPlayerName ?? 'unknown entity'}</h2>
<p>
<input ref={playerName} type="text" />
<button onClick={handleClick}>Set Name</button>
</p>
</section>
);
}
import React, { useRef, useState } from 'react';
function TimerChallenge({ title, targetTime }) {
const timer = useRef();
const [timerStarted, setTimerStarted] = useState(false);
const [timerExpired, setTimerExpired] = useState(false);
function handleStart() {
timer.current = setTimeout(() => {
setTimerExpired(true);
}, targetTime * 1000);
setTimerStarted(true);
}
function handleStop() {
clearTimeout(timer.current);
}
return (
<section className="challenge">
<h2>{title}</h2>
{timerExpired && <p>You lost!</p>}
<p className="challenge-time">
{targetTime} second{targetTime > 1 ? 's' : ''}
</p>
<p>
<button onClick={timerStarted ? handleStop : handleStart}>
{timerStarted ? 'Stop' : 'Start'} Challenge
</button>
</p>
<p className={timerStarted ? 'active' : undefined}>
{timerStarted ? 'Time is running...' : 'Timer inactive'}
</p>
</section>
);
}
export default TimerChallenge;
// 참조전달, forwardRef
- 참조를 다른 컴포넌트로 전달하고 그걸 그 컴포넌트에서 사용할 수 있게 한다.
// 전달하는 컴포넌트
<ref를 사용할 컴포넌트명
ref={ref명}
/>
// 사용하는 컴포넌트
1. 컴포넌트 함수를 감싸 상수로 저장한다.
const 컴포넌트명 = forwardRef(function 컴포넌트명() {
});
2. 두 번째 매개변수로 ref를 받는다.
const 컴포넌트명 = forwardRef(function 컴포넌트명(props, ref) {
});
3. 사용할 부분에 참조를 선언한다.
return (
<dialog ref={ref}></dialog>
);
import React, { forwardRef } from 'react';
const ResultModal = forwardRef(function ResultModal(
{ result, targetTime },
ref,
) {
return (
<dialog ref={ref} className="result-modal">
<h2>{result}</h2>
<p>
The target time was <strong>{targetTime} seconds.</strong>
</p>
<p>
You stopped the timer with <strong>X seconds left.</strong>
</p>
<form method="dialog">
<button>Close</button>
</form>
</dialog>
);
});
export default ResultModal;
function TimerChallenge({ title, targetTime }) {
const timer = useRef();
const dialog = useRef();
const [timerStarted, setTimerStarted] = useState(false);
const [timerExpired, setTimerExpired] = useState(false);
function handleStart() {
timer.current = setTimeout(() => {
setTimerExpired(true);
dialog.current.showModal();
}, targetTime * 1000);
setTimerStarted(true);
}
function handleStop() {
clearTimeout(timer.current);
}
return (
<p>
<button onClick={timerStarted ? handleStop : handleStart}>
{timerStarted ? 'Stop' : 'Start'} Challenge
</button>
</p>
);
}
export default TimerChallenge;
'클라이언트 > React' 카테고리의 다른 글
[리액트(React)] Reducer, useReducer(Hook) (0) | 2024.02.02 |
---|---|
[리액트(React)] 포탈(Portal) (1) | 2024.02.01 |
[리액트(React)] Tailwind CSS(테일윈드 CSS) 사용하기 (0) | 2024.01.30 |
[리액트(React)] 컴포넌트 동적 설정 (0) | 2024.01.23 |
[리액트(React)] forwarded props(proxy props) (0) | 2024.01.21 |