Ответ 1
Позвольте мне предвосхитить этот ответ, заявив, что все эти крючки используются очень редко. 99% времени вам это не понадобится. Они предназначены только для того, чтобы охватить некоторые редкие сценарии на углу.
useImperativeHandle
Обычно, когда вы используете useRef
вам дается значение экземпляра компонента, к ref
прикреплен ref
. Это позволяет вам напрямую взаимодействовать с элементом DOM.
useImperativeHandle
очень похож, но он позволяет вам делать две вещи:
- Это дает вам контроль над значением, которое возвращается. Вместо того, чтобы возвращать элемент экземпляра, вы явно указываете, каким будет возвращаемое значение (см. Фрагмент ниже).
- Он позволяет заменять встроенные функции (такие как
blur
,focus
и т.д.) Собственными функциями, что позволяет получить побочные эффекты для нормального поведения или совсем другого поведения. Впрочем, вы можете вызывать функцию как угодно.
Может быть много причин, по которым вы захотите сделать что-либо из вышеперечисленного; Возможно, вы не захотите предоставлять родные свойства родительскому объекту или хотите изменить поведение нативной функции. Там может быть много причин. Однако useImperativeHandle
используется редко.
useImperativeHandle
настраивает значение экземпляра, которое предоставляется родительским компонентам при использованииref
пример
В этом примере значение, которое мы получим из ref
будет содержать только функцию blur
которую мы объявили в нашем useImperativeHandle
. Он не будет содержать никаких других свойств (я регистрирую значение, чтобы продемонстрировать это). Сама функция также "настроена" на поведение, отличное от ожидаемого. Здесь он устанавливает document.title
и размывает ввод, когда вызывается blur
.
const MyInput = React.forwardRef((props, ref) => {
const [val, setVal] = React.useState('');
const inputRef = React.useRef();
React.useImperativeHandle(ref, () => ({
blur: () => {
document.title = val;
inputRef.current.blur();
}
}));
return (
<input
ref={inputRef}
val={val}
onChange={e => setVal(e.target.value)}
{...props}
/>
);
});
const App = () => {
const ref = React.useRef(null);
const onBlur = () => {
console.log(ref.current); // Only contains one property!
ref.current.blur();
};
return <MyInput ref={ref} onBlur={onBlur} />;
};
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>