react状态提升example

206 阅读1分钟

来自react文档里的状态提升小节:reactjs.org/docs/liftin…

  1. 需求大致是两个子组件共用了一个相同的state,但也不是完全的共用,具体会在render函数里进行数据的一些简单计算/转换
  2. 数据需要从共同的父组件向下传递给两个子组件
  3. 子组件有更改数据的需求,这个实现是通过:子组件调用父组件传递给它的一个function props,新值通过function的参数传递,然后在父组件里的function进行this.setState
  4. 通过这个例子也可以看到react里的父子组件通信方式:父组件向下传递props,给到子组件数据源;子组件调用props function,新值通过function的参数传递,在父组件里的这个function执行this.setState进行数据的更改
  5. vue里有一个emit方法可以通知父组件进行数据的更改;但是vue同样可以通过props function这种形式把新值通知给父组件,而不使用emit方法
// 子组件
class TemperatureInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
  // 子组件把需要更改的新值放到props function里传给父组件
    this.props.onTemperatureChange(e.target.value);  }

  render() {
    const temperature = this.props.temperature;    const scale = this.props.scale;
    return (
      <fieldset>
        <legend>Enter temperature in {scaleNames[scale]}:</legend>
        <input value={temperature}
               onChange={this.handleChange} />
      </fieldset>
    );
  }
}
// 父组件
class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
    this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
    this.state = {temperature: '', scale: 'c'};  }
    
// 子组件更改数据时会走到这个方法
  handleCelsiusChange(temperature) {
    this.setState({scale: 'c', temperature});  }

  handleFahrenheitChange(temperature) {
    this.setState({scale: 'f', temperature});  }

  render() {
    const scale = this.state.scale;
    const temperature = this.state.temperature;    
    const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;    
    const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;
    return (
      <div>
        <TemperatureInput scale="c" temperature={celsius} onTemperatureChange={this.handleCelsiusChange} />  
        <TemperatureInput scale="f" temperature={fahrenheit} onTemperatureChange={this.handleFahrenheitChange} />
        <BoilingVerdict celsius={parseFloat(celsius)} />
      </div>
    );
  }
}