一、自定义组件使用ref并且透传子组件ref
自定义组件中使用ref需要用到react的2个hooks:
1.forwardRef
2.useImperativeHandle
- useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值
- useImperativeHandle 应当与 forwardRef 一起使用
自定义组件:
const FancyInput = React.forwardRef((props, ref) => {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
// 这里可以加自己的逻辑哦
inputRef.current.focus();
}
}));
return (
<div>
<input ref={inputRef} type="text" />
<div>我是自定义的函数式组件</div>
</div>
)
});
使用:
import FancyInput from '@/components/FancyInput ';
const App = props => {
const fancyInputRef = useRef();
return (
<div>
<FancyInput ref={fancyInputRef} />
<button onClick={() => {fancyInputRef.current.focus()}}>
调用FancyInput组件的 focus方法
</button>
</div>
)
}
ReactDOM.render(<App />, root);
二、React.forwardRef和connect的联合使用问题
先使用 React.forwardRef;再使用 connect 包一层会使 ref 属性漏掉,导致 内部实例无法传到外部;
正确的操作方式要调整高阶组件的顺序,先用connect包裹,然后再用React.forwardRef包裹。
const VerificationCode = (props: VerificationCodeType) => {
useImperativeHandle(props.refInstance, () => ({ // 导出ref属性字段
myFunction(){
console.log('myFunction');
}
}));
return <></>;
};
const ConnectVerificationCode = connect( // 链接dva
({ models }: { models: ModelsType }) => ({
models,
}),
)(VerificationCode);
export default forwardRef((props: VerificationCodeType, ref) => ( // 包裹forwardRef
<ConnectVerificationCode
{...props}
refInstance={ref}
></ConnectVerificationCode>
));
这样就可以同时使用2个高阶组件了。