1) 기본 예시
// <!-- Bpage.jsx --> 컴포넌트
import { useRef } from 'react'; // 1번) 필수
function Bpage() {
const nameInput = useRef(); // 2번) 변수에 useRef()를 할당하고
// 참고) useRef()는 1번만 사용할 수 있는게 아니다. 다른 변수명에 넣으면 여러 번 똑같이 사용가능하다.
useEffect(() => { // 4번) 다음과 같이 사용할 수 있다
console.log(nameInput.current); // <input type="text" class="name1" />
console.log(nameInput.current.className); // name1
nameInput.current.classList.add('name2') // 해당 태그에 className을 추가할 수도 있다
// nameInput.current.focus(); // load되자마자 input태그를 focus상태가 되게 한다.
}, [])
return ( // 3번) ref에 useRef()를 할당한, 변수명을 넣어주면
<div>
<input type="text" ref={ nameInput } className="name1" />
</div>
)
}
export default Bpage
2) 심화 예시 (forwardRef)
// <!-- 부모 컴포넌트 -->
import React, { useRef } from 'react' // 1번) useRef
import Cat from "./Cat"
// 자식 컴포넌트 안에 있는 이미지 사이즈를 알고싶다면?
export default function CatParent() {
const catRef = useRef(); // 2번)
return (
<div>
<h4> 고양이가 세상을 구한다 </h4>
<div>
// 3번) 이때 ref는 자식 컴포넌트에서 props.ref이런식으로 사용하지 못한다.
<Cat ref={ catRef } />
// 7번) catRef로 사용하면 -> 232 이런식으로 값이 나온다 (단, 클릭했을때 이벤트가 발생하는 것이지, 화면이 리렌더링 되는 것은 아니다)
<button onClick={() => console.log(catRef.current.height)} >고양이의 크기를 알고싶어</button>
</div>
</div>
);
}
// <!-- 자식 컴포넌트 -->
import React, { forwardRef, useEffect } from "react"; // 4번) forwardRef
const Cat = forwardRef((props, ref) => { // 5번) forwardRef()로 함수전체를 감싸준다. 이때, 1번째 인자로 props를 꼭 넣어줘야한다.
useEffect(() => {
console.log("리렌더링");
console.log(ref); // {current: img}
}, []);
return (
<div>
<img
src="https://static01.nyt.com/images/2016/03/30/universal/ko/well_cat-korean/well_cat-superJumbo-v2.jpg?quality=90&auto=webp"
alt="cat"
style={{ width: "150px" }}
ref={ ref } // 6번) ref를 넣어주고
></img>
</div>
);
});
export default Cat;
const mounted = useRef(false) // 1번) 변수에 할당해서
useEffect(() => {
if (!mounted.current) {
mounted.current = true // 2번) 값을 사용, 수정 할 수는 있지만 -> 리렌더링은 X
} else {
// 함수 내용 작성
}
}, [변수명])
// <!-- 부모 컴포넌트 -->
import React, { useState } from 'react'; // useRef를 사용하지 않는다!
import Cat from "./Cat";
// 자식 컴포넌트 안에 있는 이미지 사이즈를 알고싶다면?
export default function CatParent() {
const [ height, setHeight ] = useState(0); // 1번) useState 생성하고
const catCallbackRef = (node) => { // 2번) 콜백함수 생성
console.log(node); // 6번) 자식 컴포넌트에 <img>태그
if (node !== null) { // 7번) getBoundingClientRect()는 넓이, 높이 등을 알 수 있는 내장함수
setHeight(node.getBoundingClientRect().height); // 8번) setState로 값을 업데이트하면 -> 리렌더링 발생한다
}
}
return (
<div>
<h4> 고양이가 세상을 구한다 </h4>
<h3>이미지 높이: { height }</h3> // 9번) 즉, 이 값이 업데이트되면서 -> 페이지 리렌더링
<div>
<Cat ref={ catCallbackRef } /> // 3번) useRef 대신에, 함수를 넣어주고
</div>
</div>
);
}
// <!-- 자식 컴포넌트 -->
import React, { forwardRef, useEffect, useState } from "react";
const Cat = forwardRef((props, ref) => {
useEffect(() => {
console.log("리렌더링");
console.log(ref); // 결과가 콜백함수 내용
}, []);
const [ loaded, setLoaded ] = useState(false);
return (
<div>
<img
src="https://static01.nyt.com/images/2016/03/30/universal/ko/well_cat-korean/well_cat-superJumbo-v2.jpg?quality=90&auto=webp"
alt="cat"
style={{ width: "150px" }}
ref={loaded ? ref: () => undefined} // 5번) 로드되면 -> ref에 ref 들어가고
onLoad={() => setLoaded(true)} // 4번) 이미지가 다 load된 후, 정확한 값을 가져오려고 사용
></img>
</div>
);
});
export default Cat;
const stateRef = useRef(0); // 변수를 관리하기
const tagRef = useRef(); // 특정태그 선택하기
useEffect(() => {
console.log('------ stateRef ------'); // 6번) 콜백함수는 처음 mount 될때 1번만 실행된다.
console.log(stateRef.current);
}, [stateRef.current]); // 5번) useEffect 의 배열에 ref 혹은 ref.current 를 넣을 경우, 변경을 인식하지 못하기 때문에
useEffect(() => {
console.log('------ tagRef ------'); // 8번) 콜백함수는 처음 mount 될때 1번만 실행된다.
console.log(tagRef.current);
}, [tagRef.current]); // 7번) 특정태그 선택하기 경우에도 useEffect 는 변경을 인식하지 못한다. 화면상에 innerText 가 변경되더라도, useEffect 의 배열에 ref 혹은 ref.current 를 넣을 경우, 변경을 인식하지 못하기 때문에
const changeStateRef = () => {
stateRef.current = stateRef.current + 1;
};
const changeTagRef = () => {
tagRef.current.innerText = '싫어요';
};
return (
<div>
<button onClick={changeStateRef}>변수 변경하기</button> // 1번) 아무리 클릭해도
<div>{stateRef.current}</div> // 2번) 화면에는 반영되지 않는다 (리렌더링이 발생하기 전까지는 계속 0 이다)
<button onClick={changeTagRef}>태그 innerText 변경하기</button> // 3번) 클릭하면
<div ref={tagRef}>좋아요</div> // 4번) 좋아요 -> 싫어요 로 변경된다. (특정태그 선택하기 용도로 사용했을 경우에는 DOM 을 변경하는 것이기 때문에)
</div>
)