๋ถ๋ชจ ์ปดํฌ๋ํธ์์ ์์ฑํ useRef๋ฅผ
์์ ์ปดํฌ๋ํธ์๊ฒ ๋๊ธธ ๋ ์ฌ์ฉํ๋ค.
์ฆ, ์์ ์ปดํฌ๋ํธ์ ref๋ฅผ ๋ถ๋ชจ์๊ฒ ๊ณต๊ฐํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ค.
โ๏ธ์ฐธ๊ณ ) ์์ ์ปดํฌ๋ํธ์ DOM ๋
ธ๋์ ์ ๊ทผํ๋ ๊ฒ์ ์ปดํฌ๋ํธ์ ์บก์ํ๋ฅผ ํ๊ดดํ๊ธฐ ๋๋ฌธ์ ๊ถ์ฅ๋์ง๋ ์๋๋ค.
๋ถ๋ชจ ์ปดํฌ๋ํธ
์ผ๋ฐ props์ฒ๋ผ props.ref๋ก ๋๊ธฐ์ง๋ ๋ชปํ๋ค.
// useRef ๊ฐ์ ธ์ค๊ธฐ
import React, { useRef } from "react";
import Child from "./Child"
function parents() {
const parentsRef = useRef();
return (
<>
<h2>์ฌ๊ธฐ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ</h2>
<Child ref={parentsRef}> // ์์ ์ปดํฌ๋ํธ์๊ฒ ref๋ฅผ ๋๊น
</>
)
}
์์ ์ปดํฌ๋ํธ
// forwardRef ๊ฐ์ ธ์ค๊ธฐ
import React, { forwardRef } from "react";
// ํจ์ ์์ forwardRef๋ถ์ด๊ธฐ
const Child = forwardRef (props, ref) => {
return (
<>
<img src="์ฃผ์" alt="img" ref={ref} /> // img์ ref๋ฅผ ๊ฐ์ ธ์ด
</>
)
}
export default Child;
forwardRef๋ฅผ ์ฌ์ฉํ๋ฉด ๋์ ํ๋ฅ ๋ก useImperativeHandle์ ์ฌ์ฉํ๊ฒ ๋๋ค.
ref๋ฅผ ์ฌ์ฉํ ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ์๊ฒ ๋ณด์ฌ์ง๋
์ธ์คํด์ค ๊ฐ์ ์ฌ์ฉ์ํ(customizes) ํ๋ค.
๋ถ๋ชจ ์ปดํฌ๋ํธ
// useRef ๊ฐ์ ธ์ค๊ธฐ
import React, { useRef } from "react";
import Child from "./Child"
function parents() {
const inputRef = useRef();
return (
<>
<h2>์ฌ๊ธฐ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ</h2>
<Child ref={inputRef}> // ์์ ์ปดํฌ๋ํธ์๊ฒ ref๋ฅผ ๋๊น
<button onClick={() => inputRef.current.inputFocus()}>
๋ ๋๋ฌ๋ ํฌ์ปค์ค
</button>
</>
)
}
์์ ์ปดํฌ๋ํธ
import React, { forwardRef } from "react";
// ํจ์ ์์ forwardRef๋ถ์ด๊ธฐ
const Child = forwardRef (props, ref) => {
const inputRef = useRef();// ์์์ ref๋ฅผ ๋ง๋ฌ
// ์ฒซ ๋ฒ์งธ ์ธ์๋ ๋ถ๋ชจ์ ref
// ๋ถ๋ชจ๋ ์ด ๋ก์ง์ ๋ชจ๋ฅธ๋ค.
// ์๋ก ๋์ด์ฌ๋ฆฌ๋ ๊ฒ ์๋๋ผ ๊ทธ๋ฅ ref.current๋ก ์ ๊ทผํ์ฌ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
useImperativeHandle(ref, () => {
inputFocus: () => {
inputRef.current.foucus();
}
})
return (
<>
<input ref={inputRef} ... />
</>
)
}
import React, { useRef } from "react";
import Child from "./Child"
function parents() {
const parentsRef = useRef(); // ์์์๊ฒ ๋๊ฒจ์ค ref
const myRef = useRef(0); // ๋ถ๋ชจ์์๋ง ์ฌ์ฉํ ref
const [state, setState] = useState(0);
return (
<>
<h2>์ฌ๊ธฐ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ</h2>
<Child ref={parentsRef}> // ์์ ์ปดํฌ๋ํธ์๊ฒ ref๋ฅผ ๋๊น
// ํด๋ฆญํ ๋๋ง๋ค 1 ์ฆ๊ฐ. but, ๋ฆฌ๋ ๋๋ง ์ ๋์์ ์ํ๊ณ ๊ฐ๋ง ๊ฐ์ง๊ณ ์์.
// 4๋ฒ ํด๋ฆญ ์ 4๊ฐ ์๋๊ณ 0์ผ๋ก ๋ณด์ฌ์ง.
// ์๋ "Click me!"๋ฒํผ์ ๋๋ฅด๋ฉด ๊ทธ์ ์์ผ 4๋ก ์
๋ฐ์ดํธ๋์ด ๋ณด์ฌ์ง๋ค.
<button onClick={() => (myRef.current = myRef.current + 1)}></button>
// ํด๋ฆญํ๋ฉด ์ํ๊ฐ 1 ์ฆ๊ฐ. myRef์ ๊ฐ์ด ์
๋ฐ์ดํธ ๋จ.
<button onClick={() => setState(state + 1)}>Click me!</button>
</>
)
}
๋ถ๋ชจ๊ฐ ์์ ์ปดํฌ๋ํธ์๊ฒ ref๋ฅผ ๋๊ฒจ์
์์์ด ๊ทธ ref๋ฅผ ๋ณ๊ฒฝํด๋ ๋ถ๋ชจ๋ ์์ง ๋ชปํ๋ค.
๋ง์ฝ ๋ถ๋ชจ๊ฐ ์์์๊ฒ ๋๊ธด ref๋ฅผ attachํ๊ฑฐ๋ detachํ ๋
์ด๋ค ์ฝ๋๋ฅผ ์คํํ๊ณ ์ถ๋ค๋ฉด ์ฝ๋ฐฑ ref๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
์ฆ, ์์์๊ฒ ๋๊ธด ref์ current ๊ฐ์
์์ธํ ์๊ณ ์ด๋ค ๊ฐ์ ๊ตฌํ๊ณ ์ถ์๋ ์ฌ์ฉํ๋ค.
๋ถ๋ชจ ์ปดํฌ๋ํธ
import React, { useRef } from "react";
import Child from "./Child"
function parents() {
// const parentsRef = useRef();
const [height, setHeight] = useState(0);
// ํจ์์
const callbackRef = (node) => {
if (node !== null) {
// ์์ ref์ ์ธ๋ก ๊ธธ์ด๋ก ์ํ๊ฐ ๋ณ๊ฒฝ
setHeight(node.getBoundingClientReact().height)
/* DOM ๋ฉ์๋ getBoundingClientReact๋ฅผ ์ฌ์ฉํ๋ฉด
๋งค์ฐ ๊ฐ๋จํ๊ฒ ์ํ๋ ์์์ ์์น ๊ฐ์ ์ป์ ์ ์๋ค. */
}
}
return (
<>
<h2>์ฌ๊ธฐ๋ ๋ถ๋ชจ ์ปดํฌ๋ํธ</h2>
<Child ref={callbackRef}> // parentsRef๊ฐ ์๋ ํจ์๋ฅผ ๋๊ฒจ์ค๋ค.
// ์์์ด ๋ณ๊ฒฝํ ref์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ ์ธ๋ก์ ๊ธธ์ด๋ฅผ ๋ํ๋.
<h3>์ฌ์ง ์ธ๋ก ๊ธธ์ด: {height}</h3>
</>
)
}
์์ ์ปดํฌ๋ํธ
// forwardRef ๊ฐ์ ธ์ค๊ธฐ
import React, { forwardRef } from "react";
// ํจ์ ์์ forwardRef๋ถ์ด๊ธฐ
const Child = forwardRef (props, ref) => {
// ์ํ๊ฐ ๋ง๋ค๊ธฐ
const [loaded, setLoaded] = useState(false);
return (
<>
<img src="์ฃผ์" alt="img"
ref={loaded ? ref : null} // ๋ก๋ ๋ ๋ ref
onLoad={() => setLoaded(true)} /> // ๋ก๋ ๋๋ฉด ์ํ๊ฐ ๋ณ๊ฒฝ
// why? ์ด๋ฏธ์ง๋ผ์ ๋ก๋ ์ ๋์ด์์ ๋ ๋ถ๋ชจ์์ ์ ์์ ์ผ๋ก ์๋ ์ ํ๊ธฐ ๋๋ฌธ
</>
)
}
export default Child;
๐ useRef ์ฌ์ฉ๋ฒ ๋ณด๋ฌ๊ฐ๊ธฐ
๐ (๊ณต์๋ฌธ์)useRef, Ref์ DOM
๐ (๊ณต์๋ฌธ์)forwardRef
๐ (๊ณต์๋ฌธ์)useImperativeHandle
๐ (๊ณต์๋ฌธ์)callbackRef ์ฝ๋ฐฑref