# React 父组件调用子组件的方法

3 min read
Table of Contents

在 React 中,父组件调用父组件的方法,一般用 props 回调即可。但是如果需要在父组件中调用子组件的方法?

其实核心思想就是通过 ref 来获取子组件的实例/方法。

类组件

类组件可以通过 ref 获取子组件的实例,从而调用实例的方法。

class Sub extends React.Component {
func = () => {
console.log('sub function')
}
render() {
return <div>Hello from Sub</div>
}
}
class App extends React.Component {
constructor(props) {
super(props)
this.ref = React.createRef()
}
handleBtnClick = () => {
this.ref.current.func()
}
render() {
return (
<div className="App">
<Sub ref={this.ref} />
<button onClick={this.handleBtnClick}>Click Me</button>
</div>
)
}
}

代码示例:codesandbox

函数组件

函数组件对于 ref 的处理,需要使用 forwardRef 来进行 ref 的转发。使用 forwardRef 需要指定 ref 的指向。

import { forwardRef } from 'react'
const MyInput = forwardRef(function MyInput(props, ref) {
const { label, ...otherProps } = props
return (
<label>
{label}
<input {...otherProps} ref={ref} />
</label>
)
})

上面是最常用的 ref 使用方式,指向一个 DOM 节点,可以获取 DOM 实例。但是这样子无法获取子组件的方法。

好在 React 提供了导出内部方法的钩子 useImperativeHandle

const MyInput = forwardRef(function MyInput(props, ref) {
const inputRef = useRef(null)
useImperativeHandle(ref, () => {
return {
focus() {
inputRef.current.focus()
},
scrollIntoView() {
inputRef.current.scrollIntoView()
},
}
}, [])
return <input {...props} ref={inputRef} />
})
export default function Form() {
const ref = useRef(null)
function handleClick() {
ref.current.focus()
}
return (
<form>
<MyInput placeholder="Enter your name" ref={ref} />
<button type="button" onClick={handleClick}>
Edit
</button>
</form>
)
}

代码实例:codesandbox

总结

React 父组件想要获取子组件的实例方法,必须通过 ref 来获取。而在类组件和函数组件上有部分区别。

  • 类组件可以直接通过 createRef 创建 ref 指向子组件实例,从而调用子组件内部的方法。
  • 函数组件则需要使用 useImperativeHandle 暴露子组件的方法。

参考链接


More Posts

# 自定义 Hooks

3 min read

自定义 Hooks 是一个函数,其名称以 use 开头,函数内部可以调用其他 Hooks。通过自定义 Hooks,可以将组件逻辑提取到可重用的函数中。