State提升

通常颠区,一些組件需要對同一個數據做出反應,這時我們建議將這些組件中關于這個數據的State提升至和它們距離最近的父級組件中。讓我看看該如何做到這一點:
在這個章節(jié)括袒,我們將會創(chuàng)建一個溫度計算器,根據用戶給定數值來計算水是否沸騰稿茉。
我們首先創(chuàng)建一個BoilingVerdict的組件锹锰,他接受celsius作為它的props,然后打印出水是否沸騰:

function BoilingVerdict(props) {
  if (props.celsius >= 100) {
    return <p>The water would boil.</p>;
  }
  return <p>The water would not boil.</p>;
}

接下來漓库,我們創(chuàng)建Calculator組件恃慧,它包含一個input控件,并將用戶輸入input控件的值保存在this.state.value中米苹,它依然包含上述中的BoilingVerdict組件糕伐,用來根據用戶輸入來反映水是否沸騰:

class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {value: ''};
  }

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

  render() {
    const value = this.state.value;
    return (
      <fieldset>
        <legend>Enter temperature in Celsius:</legend>
        <input
          value={value}
          onChange={this.handleChange} />
        <BoilingVerdict
          celsius={parseFloat(value)} />
      </fieldset>
    );
  }
}

在添加一個input

我們新的要求是這樣的,現在需要另一個Fahrenheit溫度的輸入框蘸嘶,它和上述Celsius的輸入框內的值保持同步良瞧。
首先我們可以將TemperatureInput組件從Calculator組件中抽象出來陪汽,我們添加一個scale的prop用來區(qū)分輸入框是Celsius還是Fahrenheit:

const scaleNames = {
  c: 'Celsius',
  f: 'Fahrenheit'
};

class TemperatureInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {value: ''};
  }

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

  render() {
    const value = this.state.value;
    const scale = this.props.scale;
    return (
      <fieldset>
        <legend>Enter temperature in {scaleNames[scale]}:</legend>
        <input value={value}
               onChange={this.handleChange} />
      </fieldset>
    );
  }
}

現在我們的Calculator輸入框可以渲染兩個不同的輸入框了:

class Calculator extends React.Component {
  render() {
    return (
      <div>
        <TemperatureInput scale="c" />
        <TemperatureInput scale="f" />
      </div>
    );
  }
}

現在我們有兩個輸入框了,但是當我們給其中一個輸入框輸入內容時褥蚯,另一個輸入框的內容不會同步改變挚冤,這不符合我們我們的需求。由于當前的溫度值被隱藏在TemperatureInput組件的內部赞庶,所以Calculator組件無法知道當前的溫度值训挡,BoilingVerdict組件也就無法知道知道水是否沸騰。

State提升

首先我們需要兩個函數歧强,它們分別將fahrenheit轉為Celsius澜薄,將Celsius轉為ahrenheit:

function toCelsius(fahrenheit) {
  return (fahrenheit - 32) * 5 / 9;
}

function toFahrenheit(celsius) {
  return (celsius * 9 / 5) + 32;
}

上面的兩個函數都起到轉換數值的作用。我們在另外寫一個函數摊册,這個函數接受一個字符串和一個函數作為參數肤京,返回值為一個字符串。當輸入一個非數字的值時茅特,它返回一個空字符串:

function tryConvert(value, convert) {
  const input = parseFloat(value);
  if (Number.isNaN(input)) {
    return '';
  }
  const output = convert(input);
  const rounded = Math.round(output * 1000) / 1000;
  return rounded.toString();
}
For example, tryConvert('abc', toCelsius) returns an empty string, and tryConvert('10.22', toFahrenheit) returns '50.396'.

Next, we will remove the state from TemperatureInput.

Instead, it will receive both value and the onChange handler by props:

class TemperatureInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    this.props.onChange(e.target.value);
  }

  render() {
    const value = this.props.value;
    const scale = this.props.scale;
    return (
      <fieldset>
        <legend>Enter temperature in {scaleNames[scale]}:</legend>
        <input value={value}
               onChange={this.handleChange} />
      </fieldset>
    );
  }
}

如果一些組件需要用相同的state時忘分,只需要把這個state提升至最近的父組件內就好。在我們的例子中白修,這個組件便是Calculator妒峦,我們把value和scale儲存到它里面。
我們可以把兩個輸入框的值都儲存起來兵睛,但是這種做法沒有必要肯骇。我們只要儲存最近一次的數值和scale就可以了,因為我們可以根據value 和scale來計算另一個scale的value:

class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
    this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
    this.state = {value: '', scale: 'c'};
  }

  handleCelsiusChange(value) {
    this.setState({scale: 'c', value});
  }

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

  render() {
    const scale = this.state.scale;
    const value = this.state.value;
    const celsius = scale === 'f' ? tryConvert(value, toCelsius) : value;
    const fahrenheit = scale === 'c' ? tryConvert(value, toFahrenheit) : value;

    return (
      <div>
        <TemperatureInput
          scale="c"
          value={celsius}
          onChange={this.handleCelsiusChange} />
         <TemperatureInput
          scale="f"
          value={fahrenheit}
          onChange={this.handleFahrenheitChange} />
        <BoilingVerdict
          celsius={parseFloat(celsius)} />
      </div>
    );
  }
}

現在卤恳,無論你在哪一個輸入框輸入數值累盗,Calculator組件中的this.state.value值和this.state.scale值都會被更新,這樣另一個沒被輸入數值的輸入框的值也會相應的被改變突琳。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末若债,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子拆融,更是在濱河造成了極大的恐慌蠢琳,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件镜豹,死亡現場離奇詭異傲须,居然都是意外死亡,警方通過查閱死者的電腦和手機趟脂,發(fā)現死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門泰讽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事已卸》鹦” “怎么了?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵累澡,是天一觀的道長梦抢。 經常有香客問我,道長愧哟,這世上最難降的妖魔是什么奥吩? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮蕊梧,結果婚禮上霞赫,老公的妹妹穿的比我還像新娘。我一直安慰自己肥矢,他們只是感情好绩脆,可當我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著橄抹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惕味。 梳的紋絲不亂的頭發(fā)上楼誓,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天械馆,我揣著相機與錄音户辞,去河邊找鬼。 笑死围橡,一個胖子當著我的面吹牛禀倔,可吹牛的內容都是我干的榄融。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼救湖,長吁一口氣:“原來是場噩夢啊……” “哼愧杯!你這毒婦竟也來了?” 一聲冷哼從身側響起鞋既,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤力九,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后邑闺,有當地人在樹林里發(fā)現了一具尸體跌前,經...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年陡舅,在試婚紗的時候發(fā)現自己被綠了抵乓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖灾炭,靈堂內的尸體忽然破棺而出茎芋,到底是詐尸還是另有隱情,我是刑警寧澤咆贬,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布败徊,位于F島的核電站,受9級特大地震影響掏缎,放射性物質發(fā)生泄漏皱蹦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一眷蜈、第九天 我趴在偏房一處隱蔽的房頂上張望沪哺。 院中可真熱鬧,春花似錦酌儒、人聲如沸辜妓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽籍滴。三九已至,卻和暖如春榴啸,著一層夾襖步出監(jiān)牢的瞬間孽惰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工鸥印, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留勋功,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓库说,卻偏偏與公主長得像狂鞋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子潜的,可洞房花燭夜當晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內容

  • React版本:15.4.2**翻譯:xiyoki ** 通常幾個組件需要響應相同的數據變化骚揍。我們建議將共享狀態(tài)提...
    前端xiyoki閱讀 668評論 0 0
  • 通常,幾個組件需要根據同一個數據變化做出響應夏块。我們建議將這個共享的狀態(tài)提升到他們最近的一個共用祖先疏咐。讓我們看看實際...
    莫銘閱讀 893評論 0 1
  • 最近看了一本關于學習方法論的書,強調了記筆記和堅持的重要性脐供。這幾天也剛好在學習React浑塞,所以我打算每天堅持一篇R...
    gaoer1938閱讀 1,672評論 0 5
  • 一 一直在追的熱劇《人民的名義》,昨晚終于落下帷幕政己。 這部戲的故事情節(jié)折射出殘酷現實和復雜人性酌壕,具有極強的感染力掏愁,...
    柴門內外閱讀 3,446評論 8 14
  • 記得去年我去寧波參加一個的婚戀課程,遇到這樣一件非常有趣的事情卵牍,我在會場認識了一個叫小孔(化名)的男孩子果港,這個小孔...
    魏康2019閱讀 413評論 0 0