《猛戳-查看我的博客地图-总有你意想不到的惊喜》
本文内容:一个父组件和两个子组件,三个组件都是函数式组件,子组件1需要调用子组件2的方法,同时子组件2需要调用子组件1的方法
子组件1通过props调用父组件的方法,父组件通过ref2调用子组件2的方法
子组件2通过props调用父组件的方法,父组件通过ref1调用子组件1的方法
注意:被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
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
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
// return this._childref = node } />
}
}
class Child extends React.Component{
getName(){
console.log('wan')
}
render(){
return <Child ref={'_childref'} />
}
}
高阶组件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变化 动态修改title
props.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);
感谢阅读,欢迎评论^-^
打赏我吧^-^