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的useImperativeHandleforwardRef

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包裹的函数子组件的各种方法和状态了,现在终于可以愉快的玩耍了

完结撒花~~~~~~~~~~~

  •