你可能不需要使用派生 state 一文出指出,当使用派生state时,书写不当很容易产生问题,所以建议任何数据,都要保证只有一个数据来源,而且避免直接复制它。但是这样就使一个组件要么受控,要么非受控,只能选其一,且为了提高灵活性,建议将组件实现为受控组件。
那么如何实现一个既受控又非受控的组件呢?下面将我的组件模版分享给大家:
其中关键是
'value' in this.props
的判断
import React, { PropTypes } from 'react';
import deepEqual from 'deep-equal';
import './style.less';
export default class MyComponent extends React.Component {
static propTypes = {
className : PropTypes.string,
value : PropTypes.number
};
static defaultProps = {
className : '',
defaultValue : 0,
//value : 0, //不能为value设置默认值,否则组件会被认为是受控组件
};
constructor(props) {
super(props);
this.state = {
value: 'value' in props ? props.value : props.defaultValue
};
this.handleChange = this.handleChange.bind(this);
}
componentDidMount() {
}
componentWillReceiveProps(nextProps) {
if ('value' in nextProps && !deepEqual(nextProps.value, this.props.value)) {
this.setState({
value: nextProps.value
});
}
}
render() {
const { value, className } = this.state;
let classes = className ? `my-component ${className}`: 'my-component';
return (
<div className={classes}>
{value}
</div>
)
}
handleChange(value) {
this.triggerChange(value);
}
triggerChange(value) {
const { onChange } = this.props;
if ('value' in this.props) {
typeof onChange === 'function' && onChange(value);
}
else {
this.setState({
value: value
}, ()=>typeof onChange === 'function' && onChange(value));
}
}
}