背景
父组件内引入了一个弹窗组件,弹窗组件使用了完全内聚的开发方法;
实现思路
父组件内通过ref获取的子组件,通过current调用子组件的方法,子组件需要通过forwardRef进行"包装"导出,通过useImperativeHandle暴露可以被current使用的方法;
父组件代码
javascript
import React, { useState, useRef } from "react";
// 引入组件
import Edit from './component/edit';
export default function Parent() {
// 定义组件ref
const editRef = useRef(null);
/**
* @method 新建
* @returns {viod}
*/
const onCreate = () => {
// 调用子组件的openModal方法
editRef.current.openModal();
};
return (
<div className="connect-page page">
<Button type="primary" onClick={onCreate}>
新建
</Button>
<Edit ref={ editRef} />
</div>
);
}
子组件代码
javascript
import React, {useState, forwardRef, useImperativeHandle} from 'react';
import {Modal } from 'antd';
function Edit(props, ref) {
// 定义弹窗状态变量
const [isModalOpen, setIsModalOpen] = useState(false);
/**
* @method 打开弹窗
* @returns {viod}
*/
const openModal = () => {
setIsModalOpen(true);
};
/**
* @method 关闭弹窗
* @returns {viod}
*/
const closeModal = () => {
console.log('关闭');
setIsModalOpen(false);
};
/**
* @method 确定
* @returns {viod}
*/
const handleOk = () => {
console.log('确定');
closeModal();
};
/**
* @method 取消
* @returns {viod}
*/
const handleCancel = () => {
console.log('取消');
closeModal();
};
useImperativeHandle(ref, () => {
return {
openModal
}
});
return (
<Modal title="新建" open={isModalOpen} onOk={handleOk} onCancel={handleCancel}>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Modal>
)
}
export default forwardRef(Edit);
踩坑
- Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
解决方案:子组件使用forwardRef进行"包装"后进行导出;
javascript
// 子组件
export default forwardRef(需要导出的组件);
- 父组件找不到子组件方法
解决方案:子组件内使用useImperativeHandle对方法进行暴露;
javascript
import React, {
// 其他引入...
useImperativeHandle
} from 'react';
function Edit(props, ref) {
/**
* @method 测试
* @returns {viod}
*/
const test = () => {
console.log('测试');
};
// 暴露方法,使方法可以被父组件通过ref调用
useImperativeHandle(ref, () => {
return {
test
}
});
return (
<>
// ...
</>
)
}
export default forwardRef(Edit);