本文代码基于React,Antd的Radio以及Radio.Group,模拟的需求是:
当有三个RadioGroup的时候,第一个RadioGroup的选择值将改变后面两个RadioGroup的状态,当第一个RadioGroup选择为1时,其他两个RadioGroup将不能使用(通过disabled来控制)。我们可以通过使用回调函数来完成这一需求:
- 首先是父组件有一个相对于三个子组件的全局的值isEnabled,这个值表示第二、第三个子组件是否可以使用,因此需要将isEnabled传给这两个子组件;
- 父组件提供一个changeEnabled方法接受一个value参数,根据这个参数,来更改isEnabled值(value为1,则为false,否则为true)。这个方法就是给子组件调用的,回调函数,将由父组件传给第一个子组件;
- 第一个子组件通过调用与RadioGroup的onClick绑定的方法handleChange,来更新它本身的value值,同时回调方法changeEnabled,并传入更新的value值;
- 父组件的changeEnabled被调用后,根据value值,及时更新自己的isEnabled值,以更改第二、第三个子组件状态。
- 在子组件中请注意render()方法中的这一行代码:const {isEnabled} = this.props,而不是将isEnabled放到子组件的constructor(props)。
总结:核心思想,即父组件拥有某个状态变量,也拥有更新这个状态变量的函数,父组件把这个函数传递给子组件,然后通过子组件的调用来更新这个状态变量。
本人是刚刚入门React不久的新手,语言组织也可能有些混乱。如有问题,请大神多多指教。
完整代码如下:
其中,
- Radios是存放一个RadioGroup的子组件,RadioGroups是父组件,存放三个Radios。
- 子组件中render()方法的这一行代码 const {isEnabled} = this.props; 尤其重要,它能够及时接收父组件的isEnabled值的变化而更新自己的RadioGroup状态。但此处笔者有个问题是,为何不能将isEnabled放到constructor里面,作为子组件本身的state值,希望有高手能够指点一下。
//RadioGroups
import React, {Component} from 'react';
import {Radio} from 'antd';
const RadioGroup = Radio.Group;
class Radios extends Component{
constructor(props){
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
value : 1, //RadioGroup初始化值为1,表示选择第一个选项
};
}
handleChange(e){
this.setState({
value : e.target.value,
});
console.log('value: ' + e.target.value + ' ' + this.props.changeEnabled);
// 子组件更新RadioGroup值的同时,回调父组件的changeEnabled方法以更新其isEnabled值,
// 如果方法为undefined,说明不是第一个RadioGroup
if(this.props.changeEnabled !== undefined){
this.props.changeEnabled(e.target.value);
console.log('changed');
}
}
render(){
//接收父组件传进来的isEnabled值,以更新子组件的状态(对应下面RadioGroup的disabled状态)
const {isEnabled} = this.props;
return (
<div>
{/*disabled值根据父组件的isEnabled改变而改变,如果为undefined,说明是第一个Radio组,不会随着父组件的isEnabled改变。*/}
<RadioGroup disabled={!isEnabled} value={this.state.value} onChange={this.handleChange}>
<Radio value={1}>1</Radio>
<Radio value={2}>2</Radio>
<Radio value={3}>3</Radio>
</RadioGroup>
</div>
);
}
}
class RadioGroups extends Component{
constructor(props){
super(props);
this.changeEnabled = this.changeEnabled.bind(this);
this.state = {
isEnabled: false,
};
}
//父组件中的回调函数(给子组件调用)
changeEnabled(value){
this.setState({
isEnabled : value !== 1
});
console.log(this.state.isEnabled)
}
render(){
return (
<div>
{/*只将回调方法传给第一个组件,这样其他两个组件的值将不影响父组件的state*/}
{/*而isEnabled第一个组件保持为true,以保证其一直可以使用*/}
<Radios isEnabled={true} changeEnabled={this.changeEnabled}/>
<Radios isEnabled={this.state.isEnabled}/>
<Radios isEnabled={this.state.isEnabled}/>
</div>
);
}
}
export default RadioGroups;
本文须知的坑:
1. 一定要学习好React的生命周期,其中每个组件的constructor只会调用一次,因此必须将要更新的值放到render方法里面而不是constructor里面,如Radios组件中render()方法里的const {isEnabled} = this.props;