反应提升状态

时间:2020-10-09 19:59:15

标签: javascript reactjs state updates

我正在研究React文档的这一部分:https://reactjs.org/docs/lifting-state-up.html

在我的一个项目中,我遇到了类似的问题,但有细微的差别。我们可以使用与文档相同的示例,并进行一些改动以适合我的问题:让我们假设我拥有<TemperatureInput />组件而不是<Sensor />。该传感器以两种不同的形式捕获温度和压力。我的第一个想法是捕获这些压力和温度输入,然后进入State(状态),然后将其传递给Sensor的props changeHandler函数,该函数实际上是一个定义并在父组件上工作的函数。这最后一部分是React文档的建议,尽管它们没有将State传递给函数,但只是一个变量(event.target.value)。因此,作为示例,我们将遇到类似这样的情况:

class Sensor extends React.Component {
  constructor(props) {
    super(props);

    this.state = {temperature:'',
                   pressure: ''}
    this.handleTemperatureChange = this.handleTemperatureChange.bind(this);
    this.handlePressureChange = this.handlePressureChange.bind(this);
  }

  handleTemperatureChange(e) {
    this.setState(temperature:e.target.value);
    this.props.onChange(this.state);
  }

  handlePressureChange(e) {
    this.setState(pressure:e.target.value);
    this.props.onChange(this.state);
  }

  render() {
    const temperature = this.props.temperature;
    return (
      <fieldset>
        <legend>Enter temperature and pressure:</legend>
        <input value={this.state.temperature}
               onChange={this.handleTemperatureChange} />
        <input value={this.state.pressure}
               onChange={this.handlePressureChange} />
      </fieldset>
    );
  }
}

我修改后的方法唯一的问题是State是异步更新的,所以当我将State传递给onChange props函数时,实际上可能是在传递先前的状态。

我不确定该如何处理。

2 个答案:

答案 0 :(得分:2)

正确。 React状态更新是异步的,因此如果尝试在使更新入队后立即访问状态,它仍将是 current 渲染周期中的状态,而不是您期望在 next <下看到的状态/ em>渲染周期。

使用组件生命周期方法(例如componentDidUpdate来处理“反应”以状态更新,并正确发出副作用,例如调用传递的回调。

class Sensor extends React.Component {
  ...

  handleTemperatureChange(e) {
    this.setState(temperature:e.target.value);
  }

  handlePressureChange(e) {
    this.setState(pressure:e.target.value);
  }

  componentDidUpdate(prevProps, prevState) {
    const { pressure, temperature } = this.state;
    if (prevState.pressure !=== pressure || 
      prevState.temperature !== temperature
    ) {
      this.props.onChange(state);
    }
  }

  render() {
    ...
  }
}

的替代方法是在状态更新后使用this.setState回调函数(第二个参数)运行函数 ,尽管我认为这种模式应该避免。 (如果误用,IMO可能会引起更多的问题,而只能解决生命周期功能

class Sensor extends React.Component {
  ...

  handleTemperatureChange(e) {
    this.setState(
      temperature:e.target.value,
      () => this.props.onChange(this.state),
    );
  }

  handlePressureChange(e) {
    this.setState(
      pressure:e.target.value,
      () => this.props.onChange(this.state),
    );
  }

  render() {
    ...
  }

似乎您的树中有较高的 压力和温度状态,因此我很好奇这种情况是否发生,并且如果只是将它们作为道具代理到输入中,将使更有意义,例如:

const Sensor = ({ pressure, onChange, temperature }) => {
  const handleTemperatureChange = (e) => {
    onChange({ temperature: e.target.value });
  }

  const handlePressureChange = (e) => {
    onChange({ pressure: e.target.value });
  }

  return (
    <fieldset>
      <legend>Enter temperature and pressure:</legend>
      <input value={temperature} onChange={handleTemperatureChange} />
      <input value={pressure} onChange={handlePressureChange} />
    </fieldset>
  );
}

答案 1 :(得分:1)

setState收到一个回调,该回调将在应用状态更改后触发。您可以在文档here中看到它。

this.setState({ ... }, () => this.props.onChange(this.state));