加入收藏 | 设为首页 | 会员中心 | 我要投稿 汽车网 (https://www.0577qiche.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

什么是React 状态提升

发布时间:2023-04-11 10:50:36 所属栏目:教程 来源:
导读:通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。让我们看看它是如何运作的。

在本节中,我们将创建一个用于计算水在给定温度下是否会沸腾的温度计算器。

我们将从
通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。让我们看看它是如何运作的。

在本节中,我们将创建一个用于计算水在给定温度下是否会沸腾的温度计算器。

我们将从一个名为 BoilingVerdict 的组件开始,它接受 celsius 温度作为一个 prop,并据此打印出该温度是否足以将水煮沸的结果。

function BoilingVerdict(props) {
  if (props.celsius >= 100) {
    return <p>The water would boil.</p>;
  }
  return <p>The water would not boil.</p>;
}
接下来, 我们创建一个名为 Calculator 的组件。它渲染一个用于输入温度的 <input>,并将其值保存在 this.state.temperature 中。

另外, 它根据当前输入值渲染 BoilingVerdict 组件。

class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {temperature: ''};
  }
 
  handleChange(e) {
    this.setState({temperature: e.target.value});
  }
 
  render() {
    const temperature = this.state.temperature;
    return (
      <fieldset>
        <legend>Enter temperature in Celsius:</legend>
        <input
          value={temperature}
          onChange={this.handleChange} />
 
        <BoilingVerdict
          celsius={parseFloat(temperature)} />
 
      </fieldset>
    );
  }
}
添加第二个输入框
我们的新需求是,在已有摄氏温度输入框的基础上,我们提供华氏度的输入框,并保持两个输入框的数据同步。

我们先从 Calculator 组件中抽离出 TemperatureInput 组件,然后为其添加一个新的 scaleprop,它可以是 "c" 或是 "f":

const scaleNames = {
  c: 'Celsius',
  f: 'Fahrenheit'
};
 
class TemperatureInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {temperature: ''};
  }
 
  handleChange(e) {
    this.setState({temperature: e.target.value});
  }
 
  render() {
    const temperature = this.state.temperature;
    const scale = this.props.scale;
    return (
      <fieldset>
        <legend>Enter temperature in {scaleNames[scale]}:</legend>
        <input value={temperature}
               onChange={this.handleChange} />
      </fieldset>
    );
  }
}
我们现在可以修改 Calculator 组件让它渲染两个独立的温度输入框组件:

class Calculator extends React.Component {
  render() {
    return (
      <div>
        <TemperatureInput scale="c" />
        <TemperatureInput scale="f" />
      </div>
    );
  }
}
我们现在有了两个输入框,但当你在其中一个输入温度时,另一个并不会更新。这与我们的要求相矛盾:我们希望让它们保持同步。

另外,我们也不能通过 Calculator 组件展示 BoilingVerdict 组件的渲染结果。因为 Calculator 组件并不知道隐藏在 TemperatureInput 组件中的当前温度是多少。

编写转换函数
首先,我们将编写两个可以在摄氏度与华氏度之间相互转换的函数:

function toCelsius(fahrenheit) {
  return (fahrenheit - 32) * 5 / 9;
}
 
function toFahrenheit(celsius) {
  return (celsius * 9 / 5) + 32;
}
上述两个函数仅做数值转换。而我们将编写另一个函数,它接受字符串类型的 temperature 和转换函数作为参数并返回一个字符串。我们将使用它来依据一个输入框的值计算出另一个输入框的值。

当输入 temperature 的值无效时,函数返回空字符串,反之,则返回保留三位小数并四舍五入后的转换结果:

function tryConvert(temperature, convert) {
  const input = parseFloat(temperature);
  if (Number.isNaN(input)) {
    return '';
  }
  const output = convert(input);
  const rounded = Math.round(output * 1000) / 1000;
  return rounded.toString();
}
例如,tryConvert('abc', toCelsius) 返回一个空字符串,而 tryConvert('10.22', toFahrenheit) 返回 '50.396'。

状态提升
到目前为止, 两个 TemperatureInput 组件均在各自内部的 state 中相互独立地保存着各自的数据。

class TemperatureInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {temperature: ''};
  }
 
  handleChange(e) {
    this.setState({temperature: e.target.value});
  }
 
  render() {
    const temperature = this.state.temperature;
    // ...
然而,我们希望两个输入框内的数值彼此能够同步。当我们更新摄氏度输入框内的数值时,华氏度输入框内应当显示转换后的华氏温度,反之亦然。

在 React 中,将多个组件中需要共享的 state 向上移动到它们的最近共同父组件中,便可实现共享 state。这就是所谓的“状态提升”。接下来,我们将 TemperatureInput 组件中的 state 移动至 Calculator 组件中去。

如果 Calculator 组件拥有了共享的 state,它将成为两个温度输入框中当前温度的“数据源”。它能够使得两个温度输入框的数值彼此保持一致。由于两个 TemperatureInput 组件的 props 均来自共同的父组件 Calculator,因此两个输入框中的内容将始终保持一致。

(编辑:汽车网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章