React 父组件如何修改子组件状态
简介
由于一个组件A中渲染的结构较多,所以我决定把组件A中使用的Antd的Modal组件拆分出去,成为一个组件B去负责处理自己的业务逻辑。
这时奇怪的问题增加了,我们需要通过组件A去控制组件B中Modal组件的显示,也就是控制Modal组件的visible属性。如果把visible放在组件A的状态中,那么组件B的Modal的onOK和onCancel属性也需要通过调用组件A定义的函数才能修改visible值。
最初想法
按照上面简介中说的,我们把组件B中Modal的visible放在组件A中进行管理,这也就是常见的父组件给子组件传值,然后通过父组件给子组件提供的方法去修改父组件的值,那么就是这样:
import React, { Component } from 'react'
import { Card, Button, Modal, Form } from 'antd'
class A extends Component {
state = {
visible: false
}
changeModalVisible = () => {
this.setState({
visible: !this.state.visible
})
}
render() {
const { visible } = this.state
return (
<Card title='示例'>
<B
visible={visible}
changeVisible={this.changeModalVisible}
/>
<Button onClick={this.changeModalVisible}>显示Modal</Button>
</Card>
)
}
}
class B extends Component {
handleOK = () => {
this.props.changeVisible()
}
render() {
const { visible, changeVisible } = this.props
return (
<Modal
title='Modal'
visible={visible}
onOk={this.handleOK}
onCancel={changeVisible}
>
<Form></Form>
</Modal>
)
}
}
export default A
上面这个案例代码省略了真实项目的大部分逻辑,项目的主要逻辑就是用户触发父组件A的一个按钮点击事件,然后显示子组件B的Modal,提供给用户一个Form表单,用户填写数据后,点击确定的时候对表单的数据进行手动收集并提交给后端,用户点击取消就隐藏掉这个Modal。
案例中的操作并没有什么不可,但实际上在我的组件A中状态和方法已经足够多了,实在是不想再往里面塞,然后我就想怎么让父组件A去修改子组件B的状态(父组件修改子组件的状态)。
使用 Refs 获得子组件
我在子组件B上添加ref属性,然后父组件A通过调用this.refs拿到子组件实例,这时就可以访问到子组件的属性和方法了。
那么,我们在子组件B中定义一个方法,这个方法实现组件对自己状态的修改操作,然后我们再在父组件A中调用这个方法就好了。
import React, { Component } from 'react'
import { Card, Button, Modal, Form } from 'antd'
class A extends Component {
showModal = () => {
this.refs.B.changeVisible()
}
render() {
return (
<Card title='示例'>
<B ref='B' />
<Button onClick={this.showModal}>显示Modal</Button>
</Card >
)
}
}
class B extends Component {
state = {
visible: false
}
changeVisible = () => {
this.setState({
visible: !this.state.visible
})
}
handleOK = () => {
this.changeVisible()
// ...
// 省略很多代码
}
render() {
const { visible } = this.state
return (
<Modal
title='Modal'
visible={visible}
onOk={this.handleOK}
onCancel={this.changeVisible}
>
<Form></Form>
</Modal>
)
}
}
export default A
对于子组件上ref属性的使用还有一个方法,给ref传一个函数而不是字符串,这时传入这个函数的参数就是组件本身,然后我们再把这个组件赋值到父组件this的一个属性上就可以更方便的调用了,比如:
class A extends Component {
showModal = () => {
this.B.changeVisible()
}
render() {
return (
<Card title='示例'>
<B ref={B => this.B = B} />
<Button onClick={this.showModal}>显示Modal</Button>
</Card >
)
}
}
另外你还可以通过React.createRef方法去创建ref然后去绑定,比如:
class A extends Component {
B = React.createRef()
showModal = () => {
this.B.current.changeVisible()
}
render() {
return (
<Card title='示例'>
<B ref={this.B} />
<Button onClick={this.showModal}>显示Modal</Button>
</Card >
)
}
}
题外话
其实最开始我都还没想到用ref实现父组件调用子组件的方法来修改子组件的状态,然后我竟然把Modal的visible放到了redux去管理,哎,我真的是脑短路。
另外,提醒下案例中用到的命名方式(比如:A、B)只为了撰写文章方便,真实开发这样用,你会凉凉的。
版权声明:
Anand's Blog文章皆为站长Anand Zhang原创内容,转载请注明出处。
包括商业转载在内,注明下方要求的文章出处信息即可,无需联系站长授权。
请尊重他人劳动成果,用爱发电十分不易,谢谢!
请注明出处:
本文出自:Anand's Blog
本文永久链接:https://anandzhang.com/posts/frontend/12