一起学习网 一起学习网


解决react-connect中使用forwardRef遇到的问题

网络编程 react-connect使用forwardRef,使用forwardRef遇到问题,react-connect使用forwardRef问题 06-18

react-connect使用forwardRef遇到的问题

项目场景

之前独立的两个tab,  tab1和tab2,  由于需求变更,  要把这两个tab都放到一个tab4下, 变化大概是从图1变为图2

原因

子组件用了使用了connect, 相当于把forwardRef隔离了,导致父组件拿不到想要的方法, 所以需要把forwardRef 透传给使用了connect 的子组件  

问题描述

tip:  该文章以下内容中说的子组件指tab1和tab2,  父组件指tab4

tab1和tab2组件都有"更新数据"按钮,将他们合并为tab4里面之后,"更新数据"按钮已经变成了父组件(tab4)的内容, 但是由于按钮的onClick事件中的逻辑太复杂,  所以点击事件没有挪出来重新写到父组件里。

也就是:按钮在父组件中,  按钮的点击事件在子组件里写。

子组件和父组件都是用函数组件 + Hook 写的, 并且子组件中都用了connect,  此时父组件想调用子组件的点击事件方法,  该怎么拿到子组件里的方法呢?

解决方案

tip:  我的项目使用的是umi2

利用Hoc(高阶组件)透传ref

import React, { forwardRef, useImperativeHandle, useState, useEffect } from 'react';import { connect } from 'dva'const Children = (props) => {  const { refInstance } = props  const [text, setText] = useState('子组件:Children')  const functionA = () => {    console.log('c2方法')    setText('ref改变了')  }  useImperativeHandle(refInstance, () => ({    functionA,    text,  }))return (    <div>      {text}    </div>)}const newA =  connect((state) => {  return {    list: state.list,  }})(Children)// 使用Hoc 透传 refexport default forwardRef((props, ref) => <newA  {...props} refInstance={ref} />);

React.forwardRef的使用说明

React.forwardRef

forwardRef实际上就是当父组件需要得到子组件元素时,可以利用forwardRef来实现。

该方法接受一个有额外ref参数的react组件函数,不调用该方法,普通的组件函数是不会获得该参数的。

应用场景

ref 的作用是获取实例,可能是 DOM 实例,也可能是 ClassComponent 的实例。

但问题来了

如果目标组件是一个 FunctionComponent 的话,是没有实例的(PureComponent),此时用 ref 去传递会报错

React.forwardRef 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。这种技术并不常见,但在以下两种场景中特别有用:

  • 转发 refs 到 DOM 组件
  • 在高阶组件中转发 refs

实例:

点击搜索按钮时,让文本输入框处于聚焦状态

1、普通用法:

import React, { Component } from 'react'export default class App extends Component {  mytext=null  render() {    return (      <div>        <button type="button" onClick={()=>{          console.log(this.mytext);          this.mytext.current.focus()          this.mytext.current.value="2222"        }}>获取焦点</button>        <Child callback={(el)=>{          console.log(el);、          //el是临时变量,用全局的去接这个值          this.mytext=el          //console.log(el.current);        }}/>      </div>    )  }}class Child extends Component {  mytext = React.createRef();  //组件渲染完了执行  componentDidMount() {    this.props.callback(this.mytext);  }  render() {    return (      <div style={{background:"yellow"}}>        <input defaultValue="1111" ref={this.mytext}></input>      </div>    );  }}

2、使用forwardRef

import React, { Component,forwardRef } from 'react'export default class App_forwardRef extends Component {  mytext=React.createRef()  render() {    return (      <div>      <button type="button" onClick={()=>{        console.log(this.mytext);        this.mytext.current.value="2222"      }}>获取焦点</button>      <Child ref={this.mytext}/>      </div>    )  }}//这里Child是函数式组件const Child=forwardRef((props,ref)=>{    return (      <div>        <input defaultValue="11111" ref={ref}></input>      </div>    );})

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。


编辑:一起学习网

标签:组件,按钮,方法,实例,函数