react函数式组件之兄弟组件中的方法互相调用

编程入门 行业动态 更新时间:2024-10-09 04:18:44

react函数式<a href=https://www.elefans.com/category/jswz/34/1771375.html style=组件之兄弟组件中的方法互相调用"/>

react函数式组件之兄弟组件中的方法互相调用

最新更新时间:2022年01月15日14:40:31
《猛戳-查看我的博客地图-总有你意想不到的惊喜》

本文内容:一个父组件和两个子组件,三个组件都是函数式组件,子组件1需要调用子组件2的方法,同时子组件2需要调用子组件1的方法

技术方案分析

兄弟组件的方法互调
  • 子组件1 -> 父组件 -> 子组件2

子组件1通过props调用父组件的方法,父组件通过ref2调用子组件2的方法

  • 子组件2 -> 父组件 -> 子组件1

子组件2通过props调用父组件的方法,父组件通过ref1调用子组件1的方法

父组件调用子组件的方法
  • 父组件通过ref获取子组件实例,然后再调用方法
  • 子组件需要用到两个hooks,forwardRef和useImperativeHandle
  • forwardRef,用户 转发refs到DOM组件 和 在高阶组件中转发refs
  • useImperativeHandle可以让你在使用ref时自定义暴露给父组件的实例值。useImperativeHandle应当和forwardRef配合使用
获取通过Form.create()()创建的函数式组件的实例
  • 通过子组件的wrappedComponentRef属性传递ref
获取被connect包裹的函数式组件的实例
  • 通过forwardRef包裹connect

注意:被withRouter、connect、Form.create等方法包裹的组件并不能抛出ref,需要使用forwardRef抛出子组件的ref

示例代码

父元素
import React, {useRef} from 'react'import Child1 form '../child1';
import Child2 form '../child2';function Parent(props){const child1Ref = useRef(null);const child2Ref = useRef(null);const child1CallChild2 = ()=>{console.log('父元素调用子元素2的方法')child2Ref.current && child2Ref.parentCallChild2()}const child2CallChild1 = ()=>{console.log('父元素调用子元素1的方法')child1Ref.current && child1Ref.parentCallChild1()}return <div><Child1 wrappedComponentRef={child1Ref} child1CallChild2={child1CallChild2}/><Child2 ref={child2Ref} child2CallChild1={child2CallChild1} /></div>
}
export default Parent
子元素1
  • 通过Form.create()(Component)创建的函数式组件,对外暴露实例和方法
import React, {forwardRef, useImperativeHandle} from 'react'
import {Form} from 'antd'function Child1(props, ref){function parentCallChild1(){console.log('父组件调用子组件1的方法')}function c1Callc2(){console.log('兄弟元素通信 子组件1调用子组件2的方法')props.child1CallChild2()}// 将parentCallChild1方法暴露给父组件获取的实例useImperativeHandle(ref,()=>({parentCallChild1}))return <div onClick={this.c1Callc2}><Form></Form></div>
}const FormComponentWrap = Form.create()(forwardRef(Child1))
export default FormComponentWrap
子元素2
  • 通过connect()()创建的函数式组件,对外暴露实例和方法
import React, {forwardRef, useImperativeHandle} from 'react'
import { connect } from 'react-redux'function Child2(props, ref){function parentCallChild2(){console.log('父组件调用子组件2的方法')}function c2Callc1(){console.log('兄弟元素通信 子组件2调用子组件1的方法')props.child2CallChild1()}// 将parentCallChild2方法暴露给父组件获取的实例useImperativeHandle(props.refInstance,()=>({parentCallChild2}))return <div onClick={this.c2Callc1}>Child2</div>
}const Component = connect(matStateToProps,mapDispatchToProps)(Child2)
export default forwardRef((props, ref)=> <Component {...props} refInstance={ref} /> )

connect方法,连接react组件与redux中的store,将数据和UI连接起来,如果不写mapStateToProps参数,UI 组件就不会订阅Store, Store 的更新不会引起 UI 组件的更新;
matStateToProps是输入源,更新props;
mapDispatchToProps是输出源,更新action;

老版本框架获取实例

//父组件
this._childRef.current.getWrappedInstance()//子组件
@connect(matStateToProps, mapDispatchToProps, mergeProps, { withRef: true })
export default connect(matStateToProps, mapDispatchToProps, mergeProps, { forwardRef: true })
export default connect(matStateToProps, mapDispatchToProps, mergeProps, { withRef: true })

获取类组件的实例

import React, {} from 'react'
import Child from '../child'
class Parent extends React.Component{constructor(){// this._childref = React.createRef();}callChildFunc(){//获取子组件实例 并调用方法this.refs._childref.getWrappedInstance().getName();this.refs._childref.wrappedInstance.getName();// this._childref.getName();}render(){return <Child ref={'_childref'} />// return <Child ref={this._childref} />// return <Child ref={ node => this._childref = node } />}
}class Child extends React.Component{getName(){console.log('wan')}render(){return <Child ref={'_childref'} />}
}

withRouter的使用

高阶组件withRouter,是将一个组件包裹进Route里面,这个组件的this.props可以获取到react-router的三个对象history, location, match

对于不是通过路由跳转过来的组件,比如首页,如果想通过props获取路由信息,就需要用withRouter包裹这个组件

或者,比如通过this.props.history.push(’/1’)跳转页面,报错history是undefined,需要用withRouter包裹组件

import React,{Component} from 'react'
import {withRouter} from 'react-router-dom'class App extends Component{//被withRouter包裹后才能获取history, match, location等路由信息对象console.log(this.props);constructor(props){super(props);// 通过history监听location变化 动态修改titleprops.history.listen((location) => {switch(location.pathname){case '/1/1' :document.title = '第一页';break;case '/1/2' :document.title = '第二页';break;default : break;}})}render(){}
}
export default withRouter(App);

扩展-父元素调用子元素的方法

父-类组件 子-类组件

父-类组件 子-函数组件

父-函数组件 子-类组件

import Child from './Child'
const childRef = React.createRef()
function Parent(){//获取子元素实例的方法或变量//childRef.current.name//childRef.current.eat()return <Child ref={childRef} />
}class Child extends React.PureComponent{constructor(props){super(props);this.eat = this.eat.bind(this);this.name = 'wanshaobo';}eat(){console.log('eat');}render(){return <div>1</div>}
}

父-函数组件 子-函数组件

import Child from './Child'
const childRef = React.createRef()
function Parent(){//获取子元素实例的方法或变量//childRef.current.name//childRef.current.eat()return <Child ref={childRef} />
}import React, {forwardRef, useImperativeHandle} from 'react'
function Child(props, ref){const name = 'wanshaobo';const eat = ()=>{console.log('eat');}useImperativeHandle(ref, ()=>({name,eat}));return <div>1</div>
}
export default forwardRef(Child);
参考资料
  • react中父组件调用子组件的方法
  • react-redux的connect用法详解
  • React 中connect和forwardRef连用会导致传入子组件的ref失效

感谢阅读,欢迎评论^-^

打赏我吧^-^

更多推荐

react函数式组件之兄弟组件中的方法互相调用

本文发布于:2024-02-27 20:13:55,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1766034.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:组件   函数   兄弟   方法   react

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!