class组件传ref到函数组件
在日常开发过程中,我们经常需要使用ref,来做一些逻辑处理。对于当前组件来说,ref的使用比较方便,而对于跨组件使用,尤其是现在hooks的广泛运用和以前的class的交叉使用,有时候会让我们使用上出现一些问题。比如在父组件中引入子组件,把ref传入到函数子组件中,会一直为空
class Home extends React.Component {
childRef = null;
render() {
return (
<Test ref={ref => this.childRef = ref} />
<Button onClick={() => {
console.log(this.childRef)
测试调用子组件方法
</Button>
子组件-函数组件
const ForwardRef = (props) => {
console.log(props)
return (
ForwardRef组件
</div>
export default ForwardRef;
子组件-class组件
class ForwardRef extends React.Component {
test = () => {
console.log('我是ForwardRef组件的test方法')
render(){
return (
ForwardRef组件
export default ForwardRef;
如上可知,在class组件中传递ref给函数组件,接收到的都是undefined,而class组件是能接收父组件传过来的ref的。那怎么能把ref从class父组件传递给函数子组件呢?react的useImperativeHandle和
forwardRef
class Home extends React.Component {
childRef = null;
render() {
return (
<Test ref={ref => this.childRef = ref} />
<Button onClick={() => {
if(this.childRef){
console.log(this.childRef.test())
测试调用子组件方法
</Button>
export default connect()(Home);
import React, {
useImperativeHandle,
forwardRef
} from 'react';
const ForwardRef = forwardRef((props, ref) => {
console.log(props)
useImperativeHandle(ref, () => ({
test,
const test = () => {
console.log('我是ForwardRef组件的test方法')
return (
ForwardRef组件
</div>
export default ForwardRef;
这样就可以在class组件中通过ref调用函数子组件的方法了。应用场景比如是在父组件中调用子组件的表单重置(有的侧边栏、弹框的单独表单验证,页面功能太多的时候,建议不同form验证放在不同的子组件。)
HOC组件ref传递(2020.09.28更新)
在react项目中,我们经常会用到HOC组件,比如为了页面出错而不至于全局崩溃的error包装组件,每个组件出错只把当前组件出错显示,而整体页面不至于崩溃。比如侧边栏、弹窗、tab切换等打开的时候,如果当前组件崩溃,只显示打印当前出错的组件显示部位,用户体验不会太差。还有我们经常使用的全局数据管理,比如dva的connect包装组件,使得组件可以使用dva的全局状态。
当前父组件代码如下:
import React from 'react';
import { connect } from 'dva';
import { Button } from 'antd';
import Test from './component/forwardRef';
class Home extends React.Component {
childRef = null;
render() {
return (
<Test ref={ref => this.childRef = ref} />
<Button onClick={() => {
if(this.childRef){
console.log(this.childRef)
测试调用子组件方法
</Button>
</div>
export default connect()(Home);
子组件为函数组件,被connect包装。
import React, {
} from 'react';
import { connect } from 'dva';
const ForwardRef = (props) => {
console.log(props)
const test = () => {
console.log('我是ForwardRef组件的test方法')
return (
ForwardRef组件
</div>
const ForwardRefWrap = connect()(ForwardRef)
export default ForwardRefWrap;
此时我们在父组件通过ref调用子组件的时候,会发现打印的其实是子组件被connect包装的HOC组件,无法获取我们真实想要的子组件,更别说调用子组件的方法了。
那我们该如何才能调用函数子组件的内部方法呢?和普通函数组件一样的调用可行吗?试一试就知道啦!
import React, {
useImperativeHandle,
forwardRef
} from 'react';
import { connect } from 'dva';
const ForwardRef = forwardRef((props, ref) => {
console.log(props)
console.log(ref)
useImperativeHandle(ref, () => ({
test,
const test = () => {
console.log('我是ForwardRef组件的test方法')
return (
ForwardRef组件
</div>
const ForwardRefWrap = connect()(ForwardRef)
export default ForwardRefWrap;
代码保存,运行。。。。。。芜湖起飞!!!!!!!!
直接报错!!!看来是不能这么用了,那么该如何使用呢?我们试试下面的方法
父组件不做修改,子组件改成下面这种,因为forwardRef函数是作为把父组件的ref传递给子组件中,并且进行包装,props和ref进行分开传递,所以应该是connect进行包装,forwardRef在最外层进行包装,才能把父组件的ref传入到子组件中。
import React, {
useImperativeHandle,
forwardRef
} from 'react';
import { connect } from 'dva';
const ForwardRef = (props) => {
console.log(props)
const {refInstance} = props;
useImperativeHandle(refInstance, () => ({
test,
const test = () => {
console.log('我是ForwardRef组件的test方法')
return (
ForwardRef组件
</div>
const ForwardRefWrap = connect()(ForwardRef)
export default forwardRef((props, ref) => <ForwardRefWrap {...props} refInstance={ref} />);
这样我们就能通过ref在父组件中调用HOC包裹的函数子组件的各种方法和状态了,现在终于可以愉快的玩耍了
完结撒花~~~~~~~~~~~