最近在项目中遇到这样一个问题:利用React.forwardRef与useImperativeHandle实现父组件调用子组件的方法,使用没问题,也能成功实现这一功能,但是当我加入connect后,功能就失效了。度娘了一下看到了这篇文章React.forwardRef和connect的联合使用问题 - 知乎,恍然大悟。
原来是先使用 React.forwardRef;再使用 connect 包一层会使 ref 属性漏掉,导致 内部实例无法传到外部;
这种外部组件是无法获取这个组件内部的实例的。
正确的操作方式要调整高阶组件的顺序,先用connect包裹,然后再用React.forwardRef包裹。
import React, { useState,useEffect,useRef, useImperativeHandle } from 'react';
import { connect } from 'umi';
import { Form } from 'antd';
import ProForm, {
ModalForm,
ProFormText,
ProFormSelect,
ProFormRadio,
ProFormCheckbox,
ProFormSwitch
} from '@ant-design/pro-form';
let LeaveRule = (props) => {
// const inputRef = useRef();
const {refInstance} = props;
const [form] = Form.useForm();
const { modalData,dispatch } = props
const [isAble,setIsAble] = useState(false)
const onVisibleChange = (e) => {
console.log(e)
setIsAble(e)
};
useImperativeHandle(refInstance, () => ({
onVisibleChange: () => {
onVisibleChange(true)
}
}));
const handleSubmite = (info) =>{
console.log(info)
// dispatch({
// type: ' checking/updateLeaveRule',
// payload:{
// id:info.id
// }
// });
}
// checking/updateLeaveRule'
useEffect(() => {
form.setFieldsValue({
name: modalData.name,
decimalNum: modalData.decimalNum,
decimalProcessing: modalData.decimalProcessing,
isIncludeHolidays: modalData.isIncludeHolidays,
timeUnit: modalData.timeUnit,
isOverdraft: modalData.isOverdraft,
minTime: modalData.minTime,
isIncludeOffDay: modalData.isIncludeOffDay,
holidayBalanceUnit: modalData.holidayBalanceUnit,
})
}, [modalData])
return (
<>
<ModalForm
form={form}
layout='horizontal'
title="新增工资套"
// ref={inputRef}
visible={isAble}
onFinish={async (info) => {
// message.success('提交成功');
// return true;
handleSubmite(info)
}}
onVisibleChange={onVisibleChange}
>
<ProForm.Group>
<ProFormText
width="120px"
name="name"
label="名称"
placeholder="请输入名称"
disabled="disabled"
/>
<ProFormRadio.Group
name="timeUnit"
label="请假单位"
options={[
{
label: '小时',
value: '小时',
},
{
label: '天',
value: '天',
}
]}
/>
</ProForm.Group>
<ProForm.Group>
<ProFormSelect
name="decimalNum"
label="保留小数点后位数:保留小数点后"
width="120px"
valueEnum={{
1: '1',
2: '2',
3: '3',
}}
placeholder="请选择"
/>
<ProFormSelect
name="decimalProcessing"
label="小数位 ,最后一位小数"
width="120px"
valueEnum={{
向上进位: '向上进位',
截断舍去: '截断舍去',
四舍五入: '四舍五入',
}}
placeholder="请选择"
/>
</ProForm.Group>
<ProForm.Group>
<ProFormText
width="100px"
name="minTime"
label="请假最小单位值"
tooltip="请假最小单位值"
placeholder="0.001"
/>
<ProFormCheckbox.Group
name="isIncludeOffDay"
label="请假时长计算"
tooltip="若勾选休息日/节假日,则表示请假时间段内的休息日/节假日也会计为请假时长。休息日/节假日的请假时长根据默认班次计算。"
options={['包含休息日', '包含节假日']}
/>
<ProFormSwitch name="isOverdraft" label="透支请假" />
</ProForm.Group>
</ModalForm>
</>
)
}
LeaveRule = connect(
({ checking: { UpdateLeaveRule}, loading }) => ({
UpdateLeaveRule,
updateLeaveRuleLoading: loading.effects['checking/updateLeaveRule'],
}),
)(LeaveRule);
// 注意:这里不要在Component上使用ref;换个属性名字比如refInstance;不然会导致覆盖
export default React.forwardRef( (props,ref) => <LeaveRule {...props} refInstance={ref} />);