useImperativeHandle可以让你在使用ref时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用ref这样的命令式代码。useImperativeHandle应当与forwardRef一起使用。
介绍:
useImperativeHandle(ref, createHandle, [deps])
- 通过useImperativeHandle可以只暴露特定的操作
- 通过useImperativeHandle的Hook, 将父组件传入的ref和useImperativeHandle第二个参数返回的对象绑定到了一起
- 所以在父组件中, 调用inputRef.current时, 实际上是返回的对象
使用:
- 父组件使用useRef(或createRef)创建一个ref对象,将这个ref对象赋给子组件的ref属性
- 子组件使用forwardRef包装自己,允许作为函数组件的自己使用ref。然后使用useImperativeHandle钩子函数,在该钩子函数的第二个函数参数中返回一些状态或方法,这个被返回的状态或方法就可以被父组件访问到。
- 父组件使用创建的ref对象的current属性获取子组件暴露出的状态或方法。
总结:
- 作用: 减少暴露给父组件获取的DOM元素属性, 只暴露给父组件需要用到的DOM方法
- 参数1: 父组件传递的ref属性
- 参数2: 返回一个对象, 以供给父组件中通过ref.current调用该对象中的方法
示例代码:
import React, { useRef, useImperativeHandle } from 'react';
import ReactDOM from 'react-dom';
const FancyInput = React.forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} type="text" />
});
const App = props => {
const fancyInputRef = useRef();
return (
<div>
<FancyInput ref={fancyInputRef} />
<button
onClick={() => fancyInputRef.current.focus()} // 调用子组件的方法
>
父组件调用子组件的 focus
</button>
</div>
)
}
ReactDOM.render(<App />, root);
OR ==>
子组件:
/**
* 图片预览组件 使用参考:
*/
import React, { useState, useImperativeHandle } from "react";
import { Dialog, Grid } from "@alifd/next";
const { Row } = Grid;
const ImagePreviewModal: React.FC<any> = ({ style, cRef }: { style: {[key: string]: string}, cRef: any }) => {
const [visible, setVisible] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(false);
const [url, setUrl] = useState<string>("");
useImperativeHandle(cRef, () => ({
onClose: () => setVisible(false),
open: (url: string) => {
setVisible(true);
setLoading(false);
setUrl(url);
}
}))
return (
<Dialog
footerActions={["cancel"]}
title={`图片预览`}
visible={visible}
onCancel={() => setVisible(false)}
onClose={() => setVisible(false)}
okProps={{ loading: loading }}
style={style}
>
<Row>
<img src={url} style={{ width: "100%" }} />
</Row>
</Dialog>
);
};
export default ImagePreviewModal;
父组件:
import React, { useEffect, useState, useRef } from "react";
import ImgPreview from "../../components/imgPreviewModal";
const Details: React.FC<any> = (props) => {
const imgPreview = useRef();
return (
<div>
<img
className="ps-form-img"
src={'imgUrl'}
alt=""
onClick={() => {
imgPreview.current.open('imgUrl');
}}
/>
<ImgPreview cRef={imgPreview} style={{ width: "750px" }} />
</div>
);
};
export default Details;