类组件
使用React.createRef()
缺点:如果子组件是嵌套了HOC,就无法指向真实子组件
//outer
import React, { useEffect } from "react";
import Inner from "./Inner";
export default function Outer() {
const innerRef = React.createRef();
return (
<div>
<p>Outer......</p>
<Inner ref={innerRef} />
<button onClick={() => innerRef.current.changeNumber()}>
outer-change-number
</button>
</div>
);
}
//inner
import React, { Component } from 'react'
export default class Inner extends Component {
constructor(props) {
super(props);
this.state = {
number:0
}
}
changeNumber = () => {
this.setState({number:++this.state.number});
}
render() {
return (
<div>
<p>{this.state.number}</p>
<button onClick={this.changeNumber}>inner-set-number</button>
</div>
)
}
}
使用ref的函数式声明
缺点:如果子组件是嵌套了HOC,就无法指向真实子组件
//outer
import Inner from "./Inner";
import React, { Component } from "react";
export default class Outer extends Component {
render() {
return (
<div>
<p>Outer......</p>
<Inner ref={node => this.Inner = node} />
<button onClick={() => this.Inner.changeNumber()}>
outer-change-number
</button>
</div>
);
}
}
//inner
import React, { Component } from 'react'
export default class Inner extends Component {
constructor(props) {
super(props);
this.state = {
number:0
}
}
changeNumber = () => {
this.setState({number:++this.state.number});
}
render() {
return (
<div>
<p>{this.state.number}</p>
<button onClick={this.changeNumber}>inner-set-number</button>
</div>
)
}
}
使用props自定义onRef属性
优点:如果子组件是嵌套了HOC,也可以指向真实子组件 缺点:需要自定义props属性
//outer
import Inner from "./Inner";
import React, { Component } from "react";
export default class Outer extends Component {
render() {
return (
<div>
<p>Outer......</p>
<Inner ref={node => this.Inner = node} />
<button onClick={() => this.Inner.changeNumber()}>
outer-change-number
</button>
</div>
);
}
}
//inner
import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
@withRouter
export default class Inner extends Component {
constructor(props) {
super(props);
this.state = {
number:0
}
}
changeNumber = () => {
this.setState({number:++this.state.number});
}
componentDidMount(){
this.props.onRef && this.props.onRef(this);
}
render() {
return (
<div>
<p>{this.state.number}</p>
<button onClick={this.changeNumber}>inner-set-number</button>
</div>
)
}
}
函数组件
使用React.createRef()和useImperativeHandle
//outer
import React from "react";
import Inner from "./Inner";
export default function Outer() {
const innerRef = React.createRef();
return (
<div>
<p>Outer......</p>
<Inner onRef={innerRef} />
<button onClick={() => innerRef.current.changeNumber()}>
outer-change-number
</button>
</div>
);
}
//inner
import React, { useImperativeHandle, useState } from "react";
export default function Inner(props) {
let [number, setNumber] = useState(0);
const changeNumber = () => {
setNumber(++number);
};
useImperativeHandle(props.onRef, () => {
return {
changeNumber,
};
});
return (
<div>
<p>{number}</p>
<button onClick={changeNumber}>inner-set-number</button>
</div>
);
}
如果父组件使用ref,则子组件需要使用forwardRef
//outer
import React from "react";
import Inner from "./Inner";
export default function Outer() {
const innerRef = React.createRef();
return (
<div>
<p>Outer......</p>
<Inner ref={innerRef} />
<button onClick={() => innerRef.current.changeNumber()}>
outer-change-number
</button>
</div>
);
}
//inner
import React, { forwardRef, useImperativeHandle, useState } from "react";
const Inner = forwardRef((props,ref)=>{
let [number, setNumber] = useState(0);
const changeNumber = () => {
setNumber(++number);
};
useImperativeHandle(ref, () => {
return {
changeNumber,
};
});
return (
<div>
<p>{number}</p>
<button onClick={changeNumber}>inner-set-number</button>
</div>
);
})
export default Inner;
总结
- 类组件推荐使用props自定义onRef属性,无论组件嵌套多少层HOC,均能获取到
- 函数组件使用React.createRef()和useImperativeHandle