useImperativeHandle可以让你在使用ref时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用ref这样的命令式代码。useImperativeHandle应当与forwardRef一起使用。
useImperativeHandle(ref, createHandle, [deps])
通过useImperativeHandle可以只暴露特定的操作
通过useImperativeHandle的Hook, 将父组件传入的ref和useImperativeHandle第二个参数返回的对象绑定到了一起
所以在父组件中, 调用inputRef.current时, 实际上是返回的对象
useImperativeHandle使用简单总结:
作用: 减少暴露给父组件获取的DOM元素属性, 只暴露给父组件需要用到的DOM方法
参数1: 父组件传递的ref属性
参数2: 返回一个对象, 以供给父组件中通过ref.current调用该对象中的方法
实例:
父组件:
import React, { useState, useEffect, useRef } from 'react';
const cRef = useRef() as React.MutableRefObject;
//使用子组件暴露出来的方法 cRef.current
const handleAgree = async () => {
const res = await cRef.current.onFinish();
}
//CloudIntelligence 子组件
子组件:
import React, { useState, useImperativeHandle, useEffect } from 'react';
//子组件解析出来
const { cRef, data } = props;
// 将方法暴露给父组件使用
useImperativeHandle(cRef, () => ({
form,
onFinish,
}));
回顾一下ref和forwardRef结合使用:
import React, { useRef, forwardRef } from 'react'
// forwardRef可以将ref转发给子组件
const JMInput = forwardRef((props, ref) => {
return
})
export default function ForwardDemo() {
// forward用于获取函数式组件DOM元素
const inputRef = useRef()
const getFocus = () => {
inputRef.current.focus()
}
return (
)
}
forwardRef的做法本身没有什么问题, 但是我们是将子组件的DOM直接暴露给了父组件:
import React, { useState, useContext } from 'react';
import { ChildrenContext } from '../index';
import { Button } from 'antd';
export const Children= (props) => {
const { setParent } = props;
const baseval = useContext(ChildrenContext);
const onClick= () => {
setParent(false);
}
return (
);
}
父组件
import React, { useState, createContext } from 'react';
import {Children} from './Children.js';
export const ChildrenContext = createContext();
export const Parent = () => {
const [parent, setChildren] = useState(false);
return (
);
}
参考来源:
React Hook 中useImperativeHandle介绍使用与场景 - 网页3剑客