focus test 버튼을 누르면 input으로 이동해서 포커싱이 되도록 해보자.
아래의 코드로 시작한다.
import { useState, useEffect } from "react";
function App() {
const [temp, setTemp] = useState([]);
useEffect(() => {
let t = [];
for (let i = 0; i < 100; i++) t.push(i);
setTemp(t);
}, []);
return (
<div className="App">
<button>focus test</button>
{temp.map((item, idx) => (
<p key={idx}>{item}번째 p tag</p>
))}
<input type="text"/>
</div>
);
}
export default App;
focus test 버튼을 누르면 맨 아래의 input으로 이동하도록 해보자.
useRef 선언
focus 기능을 사용하기 위해서는 useRef를 이용한다.
import { useState, useEffect, useRef } from "react";
function App() {
const focusTest = useRef(null);
만든 useRef인 focusTest를 input의 ref에 설정하자.
<input type="text" ref={focusTest}></input>
이제 버튼을 누르면 아래의 input으로 이동한다.
전체 코드는 다음과 같다.
import { useState, useEffect, useRef } from "react";
function App() {
const focusTest = useRef(null);
const [temp, setTemp] = useState([]);
useEffect(() => {
let t = [];
for (let i = 0; i < 100; i++) t.push(i);
setTemp(t);
}, []);
return (
<div className="App">
<button onClick={() => focusTest.current.focus()}>focus test</button>
{temp.map((item, idx) => (
<p key={idx}>{item}번째 p tag</p>
))}
<input type="text"></input>
</div>
);
}
export default App;
여러 개의 useRef
여러 input으로 이동하려면 useRef를 더 선언하면 된다.
예를 들면 아래와 같다.
import { useState, useEffect, useRef } from "react";
function App() {
const focusTest = useRef(null);
const focusTest2 = useRef(null);
const focusTest3 = useRef(null);
const [temp, setTemp] = useState([]);
useEffect(() => {
let t = [];
for (let i = 0; i < 100; i++) t.push(i);
setTemp(t);
}, []);
return (
<div className="App">
<button onClick={() => focusTest.current.focus()}>focus test</button>
<button onClick={() => focusTest2.current.focus()}>focus test2</button>
<button onClick={() => focusTest3.current.focus()}>focus test3</button>
{temp.map((item, idx) => (
<p key={idx}>{item}번째 p tag</p>
))}
<input type="text" ref={focusTest}></input>
<input type="text" ref={focusTest2}></input>
<input type="text" ref={focusTest3}></input>
</div>
);
}
export default App;
위의 코드라면 focus test3 버튼을 누르면 세 번째 input으로 이동한다.
▼
하지만 더 간결하게 하려면 useRef를 배열로 선언하면 된다.
const focusTest = useRef([]);
input의 ref는 아래와 같이 코드가 변경된다.
<input type="text" ref={(val) => (focusTest.current[0] = val)}></input>
<input type="text" ref={(val) => (focusTest.current[1] = val)}></input>
<input type="text" ref={(val) => (focusTest.current[2] = val)}></input>
focus()를 호출하는 부분은 아래와 같이 변하게 된다.
<button onClick={() => focusTest.current[0].focus()}>focus test</button>
<button onClick={() => focusTest.current[1].focus()}>focus test2</button>
<button onClick={() => focusTest.current[2].focus()}>focus test3</button>
전체 코드는 다음과 같다.
import { useState, useEffect, useRef } from "react";
function App() {
const focusTest = useRef([]);
const [temp, setTemp] = useState([]);
useEffect(() => {
let t = [];
for (let i = 0; i < 100; i++) t.push(i);
setTemp(t);
}, []);
return (
<div className="App">
<button onClick={() => focusTest.current[0].focus()}>focus test</button>
<button onClick={() => focusTest.current[1].focus()}>focus test2</button>
<button onClick={() => focusTest.current[2].focus()}>focus test3</button>
{temp.map((item, idx) => (
<p key={idx}>{item}번째 p tag</p>
))}
<input type="text" ref={(val) => (focusTest.current[0] = val)}></input>
<input type="text" ref={(val) => (focusTest.current[1] = val)}></input>
<input type="text" ref={(val) => (focusTest.current[2] = val)}></input>
</div>
);
}
export default App;
<p> 태그에 포커스 맞추기 (tabIndex)
먼저 아래와 같이 코드를 수정해서 N번째 p 태그로 이동하도록 해보자.
input에 입력받은 태그로 이동하도록 useState로 input + button을 추가하였다.
import { useState, useEffect, useRef } from "react";
function App() {
const focusTest = useRef([]);
const pTagFocus = useRef([]); /* <p> 태그 포커스 용 useRef */
const [temp, setTemp] = useState([]);
const [number, setNumber] = useState("");
useEffect(() => {
let t = [];
for (let i = 0; i < 100; i++) t.push(i);
setTemp(t);
}, []);
return (
<div className="App">
<input value={number} onChange={(e) => setNumber(e.target.value)} />
<button
onClick={() => {
pTagFocus.current[number].focus();
}}
>
번째 p 태그로 이동
</button>
<button onClick={() => focusTest.current[0].focus()}>focus test</button>
<button onClick={() => focusTest.current[1].focus()}>focus test2</button>
<button onClick={() => focusTest.current[2].focus()}>focus test3</button>
{temp.map((item, idx) => (
<p
key={idx}
ref={(val) => (pTagFocus.current[idx] = val)}
>
{item}번째 p tag
</p>
))}
<input type="text" ref={(val) => (focusTest.current[0] = val)}></input>
<input type="text" ref={(val) => (focusTest.current[1] = val)}></input>
<input type="text" ref={(val) => (focusTest.current[2] = val)}></input>
</div>
);
}
export default App;
그런데 버튼을 눌러도 아무 반응이 없다.
포커스가 가능한 태그는 여러 개가 있는데, 대표적으로 input, button, textarea 등이다.
그 외 <p> 태그나 <div> 태그등은 포커스가 불가능하다.
위의 태그도 포커싱이 되려면 tabIndex를 설정하면 된다.
<p
key={idx}
ref={(val) => (pTagFocus.current[idx] = val)}
tabIndex={idx}
>
{item}번째 p tag
</p>
이제 <p> 태그로도 정상적으로 포커싱이 된다.
전체 코드는 다음과 같다.
import { useState, useEffect, useRef } from "react";
function App() {
const focusTest = useRef([]);
const pTagFocus = useRef([]); /* <p> 태그 포커스 용 useRef */
const [temp, setTemp] = useState([]);
const [number, setNumber] = useState("");
useEffect(() => {
let t = [];
for (let i = 0; i < 100; i++) t.push(i);
setTemp(t);
}, []);
return (
<div className="App">
<input value={number} onChange={(e) => setNumber(e.target.value)} />
<button
onClick={() => {
pTagFocus.current[number].focus();
}}
>
번째 p 태그로 이동
</button>
<button onClick={() => focusTest.current[0].focus()}>focus test</button>
<button onClick={() => focusTest.current[1].focus()}>focus test2</button>
<button onClick={() => focusTest.current[2].focus()}>focus test3</button>
{temp.map((item, idx) => (
<p
key={idx}
ref={(val) => (pTagFocus.current[idx] = val)}
tabIndex={idx}
>
{item}번째 p tag
</p>
))}
<input type="text" ref={(val) => (focusTest.current[0] = val)}></input>
<input type="text" ref={(val) => (focusTest.current[1] = val)}></input>
<input type="text" ref={(val) => (focusTest.current[2] = val)}></input>
</div>
);
}
export default App;
댓글