input์ ์๋ ํฌ์ปค์ฑ์ ์ด๋ ๊ฒ autoFocus ์์ฑ์ ์ค๋ ๊ฐ๋จํ ๊ฐ๋ฅํ๋ค. ํ์ง๋ง hooks๋ก ๊ตฌํํด๋ณด๋ ค๊ณ ํ๋ค.
<input
// ref={searchBarRef}
className="search-bar"
placeholder="Search"
value={keyword}
onChange={(e) => updateField("keyword", e.target.value)}
autoFocus
/>
(์ฐธ๊ณ ํ ์ฝ๋)
autocomplete searchBar๋ฅผ ๊ตฌํํ๋ ์ค์ ํ์ด์ง์ ๋ค์ด๊ฐ์ ๋ auto focusing ๋๋ ๊ฒ์ ๊ตฌํํ๋๋ฐ, useRef๋ฅผ ์ฌ์ฉํด์ input ์๋ฆฌ๋จผํธ์ ref๋ฅผ ์ก์์ focus()๋ฅผ ํธ์ถํด์ฃผ๋ ค๊ณ ํ์ง๋ง ํ์
์คํฌ๋ฆฝํธ๋ฅผ ์ ์ฉํ ๋ฆฌ์กํธ ํ๋ก์ ํธ์ฌ์ ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
ย
DOM ์์๊ฐ ๋ง์ดํธ๋ ์ดํ์ focus()์ํค๋ ค๊ณ ํ์ง๋ง useRef(null)์ ํ ๋นํ๋ฉด ๊ฐ์ฒด searchBarRef๊ฐ null์ด ๋ ์ํ์์ useEffect()๊ฐ ํธ์ถ๋๋ ์์์ด๋ค. ์ค์ ๋ก ๊ทธ๋ ๊ฒ ๋์ํ์ง ์์ง๋ง. ์ฝ๋ ์์๋ ๊ทธ๋ ๋ค.
๋ฐ์์ return ๋ฉ์๋ ๋ด์ DOM ์์๋ค์ด ๋ถ๋ฌ์ง๊ณ ๋์ useEffect๋ ํธ์ถ๋ ๊ฒ์ด๋ค. ๋ฐ๋ผ์ ์๋์ ๊ธ์์๋ ์ด๊ฒ๋ง ์์ฑํด๋ ์ ๋์ํ๋ค๊ณ ํ์ง๋ง ํ์
์คํฌ๋ฆฝํธ๋ ์๋ฌ๋ฅผ ๋ณด์ฌ์คฌ๋ค.
ํ์
์ ๋ง์ถฐ์ฃผ๋ ค๊ณ useRef์ HTMLInputElement๋ฅผ ์ฃผ๊ณ ๋ด๋ถ์์ ์กฐ๊ฑด๋ฌธ์ผ๋ก ์ฒดํฌ๋ ํด์ฃผ์๋ค. (์๋๋ฉด if๋ฌธ์ผ๋ก null์ ๊ฒ์ฌํ ๊ฒ์ ์ต์
๋ ์ฐ์ฐ์ ?๋ก searchBarRef.current?.focus()๋ก ์ฒดํฌํด์ค ์ ์๋ค.)
const searchBarRef = React.useRef<HTMLInputElement>(null);
React.useEffect(() => {
ย
์ด๋ ๊ฒ ๊ตฌํ์ ํ๋ค๊ฐ ์ฌ๋ฌ ๋ฒ ์ฌ์ฉ๋ ๊ฒ์ผ๋ก ์๊ฐ๋์ auto focus๋ฅผ ํด์ค ์ ์๋ ์ปค์คํ
ํ
์ ๋ง๋ค์ด์ผ๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค. ์ด๋ฏธ ์ ๋ง๋ค์ด์ง ๊ฒ๋ค์ด ์๊ฒ ์ง๋ง ํผ์ ๊ตฌํํด๋ณด๋ฉด์ ์ดํดํ๋ ๊ฒ์ด ๋์์ด ๋ ๊ฒ ๊ฐ์๋ค.
useAutofocus hook์ ๋ง๋ค์๋๋ ์ฌ์ฉํ๋ ๊ณณ์์ ์๋ฌ๋ฅผ ๋๋ค. ์๋ํ๋ฉด ๊ณต์ฉ์ผ๋ก ์ฌ์ฉํด์ผ ํด์ useRef<HTMLElement>๋ก type scope๋ฅผ ๋ํ์ ์ง์ ํด๋์๊ธฐ ๋๋ฌธ์ด๋ค.
RefObject<HTMLElement> is not assignable to type 'LegacyRef<HTMLInputElement> | undefined.
ย
์ด๊ฑธ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ 2๊ฐ์ง๊ฐ ์๋ค.
(ํ์
์คํฌ๋ฆฝํธ ํธ๋๋ถ์ ์ฐธ๊ณ ํ๋ค. https://joshua1988.github.io/)
์ฒซ๋ฒ์งธ๋ as๋ฅผ ์ฌ์ฉํด์ ๊ตฌ์ฒด์ ์ผ๋ก ํ์
์ ์ง์ ํด์ฃผ์ด์ผ ํ๋๋ฐ ์ด๊ฒ์ ํ์
๋จ์ธ(Type Assertion)์ด๋ผ ํ๋ค.
ํ์ ๋จ์ธ(Type Assertion)
ํ์
๋จ์ ์ ๊ฐ๋ฐ์๊ฐ ํด๋น ํ์
์ ๋ํด ํ์ ์ด ์์ ๋ ์ฌ์ฉํ๋ ํ์
์ง์ ๋ฐฉ์์
๋๋ค. ๋ค๋ฅธ ์ธ์ด์ ํ์
์บ์คํ
๊ณผ ๋น์ทํ ๊ฐ๋
์ด๋ฉฐ ํ์
์คํฌ๋ฆฝํธ์์ ํน๋ณํ ํ์
์ ์ฒดํฌํ์ง ์๊ณ , ๋ฐ์ดํฐ์ ๊ตฌ์กฐ๋ ์ ๊ฒฝ์ฐ์ง ์์ต๋๋ค.(ํ์
์คํฌ๋ฆฝํธ ํธ๋๋ถ)
import React from "react";
export function useAutofocus() {
const ref = React.useRef(null);
React.useEffect(() => {
ref.current?.focus();
}, [ref]);
return ref;
}
// searchBar.tsx
const searchBarRef = useAutofocus();
...
<input
ref={searchBarRef as React.RefObject<HTMLDivElement>}
...
/>
์ด๋ ๊ฒ ํ๋ฉด ์ฌ์ฉํ ๋๋ง๋ค ํ์
๋จ์ธ์ผ๋ก ์ ์ ์๋ํ๊ฒ ๋ง๋ค ์ ์์ง๋ง ํ์
์คํฌ๋ฆฝํธ๋ ์ด๋ด ๋ ์ฌ์ฉํ ์ ์๋ ๊ฐ๋
์ ์ด๋ฏธ ๊ฐ์ง๊ณ ์๋ค. ๊ทธ๊ฒ ๋๋ฒ์งธ๋ค.
ย
๋๋ฒ์งธ๋ก๋ ์ ๋ค๋ฆญ(Generics)์ ์ฌ์ฉํ๋ ๋ฐฉ์์ด ์๋ค.
์ ๋ค๋ฆญ(Generics)์ ์ฌ์ ์ ์ ์
์ ๋ค๋ฆญ์ C#, Java ๋ฑ์ ์ธ์ด์์ ์ฌ์ฌ์ฉ์ฑ์ด ๋์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ๋ ์์ฃผ ํ์ฉ๋๋ ํน์ง์
๋๋ค. ํนํ, ํ๊ฐ์ง ํ์
๋ณด๋ค ์ฌ๋ฌ ๊ฐ์ง ํ์
์์ ๋์ํ๋ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ๋๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
์ ๋ค๋ฆญ์ด๋ ํ์
์ ๋ง์น ํจ์์ ํ๋ผ๋ฏธํฐ์ฒ๋ผ ์ฌ์ฉํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
๊ธฐ๋ณธ์ ์ธ ์์ ๋ ์๋์ ๊ฐ๋ค.
ย
์ ๋ค๋ฆญ ํ์
์ ์ ์ฉํ๋ฉด HTMLElementํ์
์ ํฌํจ๋๋ T๋ก ๋ฐ์ ์ปค์คํ
ํ
์ ๊ตฌ์ฑ์ํฌ ์ ์๋ค.
์ด ๊ฒฝ์ฐ ์๋ฌ๊ฐ ์ฌ๋ผ์ง๊ฒ ๋๋ค.
const searchBarRef = useAutofocus<HTMLInputElement>();
...
<input
ref={searchBarRef}
/>
...
// useAutofocus()
import React from "react";
export function useAutofocus<T extends HTMLElement>() {
const ref = React.useRef<T>(null);
React.useEffect(() => {
ref.current?.focus();
}, [ref]);
return ref;
}
๋ฆฌ์กํธ์ ํ์
์คํฌ๋ฆฝํธ ๊ตฌ์กฐ๋ฅผ ์์ฃผ ์ฌ์ฉํ๊ณ ์๋๋ฐ ์ด๋ฒ ์๋ฌ๋ฅผ ํด๊ฒฐํ๋ฉด์ ํ์
์คํฌ๋ฆฝํธ ํธ๋๋ถ์ ์ข
์ข
๋ด์ผํ๋ค๋ ์๊ฐ๊ณผ ์ดํํฐ๋ธ ํ์
์คํฌ๋ฆฝํธ๊ฐ ์ ๋ช
ํ๋๋ฐ ๊ทธ ์ฑ
์ ์ฌ์ ๊ณต๋ถํด๋ณผ๊น ์ถ์๋ค. ์ต๊ทผ ๋ค์ด ๊ธฐ๋ณธ๊ธฐ๋ฅผ ๋ค์ง๊ธฐ ์ํด์ ๋ฐ๋๋ผ ์๋ฐ์คํฌ๋ฆฝํธ ์์ฃผ๋ก ๊ณต๋ถํด์ ํท๊ฐ๋ฆฌ๋ ๋ถ๋ถ๋ค์ด ์์๋๋ฐ ์ญ์ ๊พธ์คํ ๊ณต๋ถํด์ผ ํ๋ค.
ย