사용자가 정의한 컴포넌트에 Ref를 전달하고 싶을때 사용합니다.
사용자가 정의한 Input 컴포넌트가 다음과 같이 있을 때
const Input = (props) => {
return (
<div className={classes.input}>
<label htmlFor={props.input.id}>{props.label}</label>
<input {...props.input} />
</div>
);
};
이 컴포넌트를 사용하는 부모컴포넌트에서 이 컴포넌트의 input의 ref가 필요한 상황입니다!
import React, { useRef, useState } from 'react';
import Input from '../../UI/Input';
import classes from './MealItemForm.module.css';
const MealItemForm = (props) => {
const amountInputRef = useRef();
return (
<form className={classes.form}>
<Input
ref={amountInputRef} ❗️❗️❗️❗️❗️❗️
label='Amount'
input={{
id: 'amount_' + props.id,
type: 'number',
min: '1',
max: '5',
step: '1',
defaultValue: '1',
}}
/>
</form>
);
};
export default MealItemForm;
하지만 위 코드의 Input 컴포넌트의 ref를 얻을수가 없습니다. (사용자 정의 컴포넌트이기때문에, HTML 태그가 아님!)
위와 같은 상황일 때 ref를 얻기위해 사용합니다.
Input 컴포넌트를 다음과 같이 수정하면 부모 컴포넌트가 ref를 핸들링 할 수 있게됩니다.
import React from 'react';
import classes from './Input.module.css';
const Input = React.forwardRef((props, ref) => {
return (
<div className={classes.input}>
<label htmlFor={props.input.id}>{props.label}</label>
<input ref={ref} {...props.input} />
</div>
);
});
export default Input;
useImperativeHandle은 ref를 사용할 때 부모 컴포넌트에 노출되는 인스턴스 값을 사용자화(customizes)합니다.
function ParentComponent() {
// 부모는 inputRef.current로 접근하여 자식의 메소드에 접근할 수 있습니다.
const inputRef = useRef();
return (
<>
<FancyInput ref={inputRef} />
<button onClick={() => inputRef.current.realllyFocus()}>포커스</button>
</>
)
}
function FancyInput = React.forwardRef((props, ref) {
// 부모는 이 로직에 대해 모르고, 위로 끌어올리지 않고도 그냥 ref.current로 접근하여 사용만 하면 된다
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
reallyFocus: () => {
inputRef.current.focus();
console.log('Being focused!')
}
}));
// ref는 input을 참조하고 있다.
return <input ref={inputRef} />
})
참조
https://velog.io/@whwkd11010/Ref-forwardRef-useImperativeHandle