上一節:表單
很多情況下我們使用的多個元件需要對同乙個資料做出對應的反應。在這裡我們推薦把這個共享的狀態提公升到距離這些元件最近的祖先元件。現在讓我們來看看這是怎麼工作的。
在本章中,我們將會建立乙個溫度計算器來計算在給定溫度下水是否會沸騰。
首先我們現建立乙個boilin**erdict
元件。它接收乙個celsius
(攝氏度)作為prop
,並在頁面上列印出在這個溫度下水是否會沸騰。
function boilin**erdict(props)
return the water would not boil.
;}
接下來,我們將會建立乙個calculator
元件。它渲染了乙個輸入框來輸入溫度並將輸入值繫結到this.state.temperature
。
除此之外,它也為當前輸入的溫度渲染相應的boilin**erdict
。
class calculator extends react.component ;
} handlechange(e) );
} render()
}
現在我們有乙個新需求,除了輸入攝氏溫度之外,我們還需要乙個能夠輸入華氏溫度的輸入框,並且這兩個輸入框是同步的。
首先我們可以從calculator
元件中提取出乙個temperatureinput
元件。並新增乙個scale
作為prop來代表攝氏度(c)或華氏溫度(f)。
const scalenames = ;
class temperatureinput extends react.component ;
} handlechange(e) );
} render() :
);}}
現在我們可以更改calculator
元件來渲染兩個不同的溫度輸入。
class calculator extends react.component
}
現在我們有了兩個輸入框,但是當你在其中乙個輸入時另乙個輸入框內的資料並不會更新。這就與我們想要這兩個輸入框同步的需求矛盾了。
我們也沒法在calculator
中展示boilin**erdict
了,因為calculator
元件沒有辦法獲取到隱藏在temperatureinput
元件裡的溫度。
為了解決上述的矛盾,我們現編寫能夠相互轉換攝氏度和華氏溫度的兩個函式。
function tocelsius(fahrenheit)
function tofahrenheit(celsius)
這兩個函式用來轉換數字,現在我們來編寫另乙個函式,這個函式講temperature
字串和轉換函式作為引數並返回乙個字串。我們使用這個函式根據其中乙個輸入框的資料來計算另乙個輸入框的資料。
同時如果輸入的溫度無效那麼就返回乙個空字串,對有效的溫度返回精確到小數點後三位的數字。
function tryconvert(temperature, convert)
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 ;
} handlechange(e) );
} render() );
this.props.ontemperaturechange(e.target.value);
// ...
提示temperature和ontemperaturechange在這裡沒有特殊的含義,只是乙個屬性名稱,是可以隨意定義的,它也可以是更大眾化的value和onchange。
ontermperaturechange
屬性和temperature
屬性都是由父元件calculator
提供的。它會通過修改自身的state來處理資料的變化,以此來重新渲染兩個輸入框內的資料。我們很快就可以看到calculator
元件的實現細節。
在我們深入了解calculaor
元件的實現之前,先讓我們來回顧一下temperatureinput
元件做了哪些修改。我們將移除了本地state,將原本通過讀取this.state.temperature
獲取溫度替換成讀取this.props.temperature
獲取,將通過呼叫setstate()
修改資料替換成呼叫this.props.ontemperaturechange()
修改資料,這兩種都由calculator
元件提供。
class temperatureinput extends react.component
handlechange(e)
render() :
);}}
現在讓我們來看看calculator元件。
我們將輸入框的temperature和scale儲存在本地state中,這是我們從input中提公升出來的狀態,來作為兩個input的資料來源。這就是我們渲染兩個input需要的最小資料集合。
舉個例子,現在我們在攝氏度輸入框內輸入37,那麼calculator元件的state就將會是這樣:
如果之後我們在華氏溫度輸入框中輸入212,calculator的state就將變成:
有人會說為什麼儲存兩個input的值?可以,但沒必要。只要儲存最近修改的值和它所代表的scale就足夠了。因為我們可以根據當前的temperature和scale推算出另乙個input的值。
現在,輸入框的值是同步的了,因為它們的值都是由同一狀態計算出來的。
class calculator extends react.component ;
} handlecelsiuschange(temperature) );
} handlefahrenheitchange(temperature) );
} render()
}
現在,無論你在哪個輸入框輸入,calculator
元件的this.state.scale
和this.state.temperature
都會更新。其中乙個輸入框的輸入按照原樣取值,於是使用者的輸入就這樣被儲存了,而另乙個輸入框的值就會根據使用者的輸入推算出來。
讓我們梳理以下當我們在乙個輸入框輸入時**的執行邏輯:
每一次更新都按照上述步驟進行,所以兩個輸入框資料可以保持同步。
在react應用中任何可變的資料都應該有唯一資料來源。通常來說,state一開始都是包含在需要根據它來渲染資料的元件中。但是如果有其他元件也想要使用這個state,那麼就需要把它提公升到距離這兩個元件最近的公共父元件中。但是相比於保持不同元件的資料同步,我們更應該依靠的是自頂而下的資料流。
相較於雙向繫結,狀態提公升需要編寫更多的「樣板」**。但這樣做的好處是我們可以更好地定位和分離bug。因為state只存在於各自的元件中,所以bug出現範圍就大大減少了。除此之外,我們可以自由地實現任何邏輯來拒絕或修改使用者輸入。
如果某個資料可以根據state或者props推導出來,那麼這個資料就不應該儲存在state中。就像本章的例項**中,我們只儲存最新輸入的溫度和它對應的scale,並不需要將華氏溫度和攝氏溫度都儲存在state中。另乙個輸入框的資料在呼叫render()方法時就可以根據當前的資料推算出來。這能讓我們清除使用者輸入或者在不損失使用者輸入精度的情況下在其他區域使用使用者輸入的值。
當頁面出現錯誤時,你可以使用react developer tools檢視props並且在元件樹上追溯源頭直到找到對應的元件為止。這能夠讓你輕鬆地定位bug。
上一節:表單
React狀態提公升
react狀態提公升 react中的狀態提公升概括來說,就是將多個元件需要共享的狀態提公升到它們最近的父元件上.在父元件上改變這個狀態然後通過props分發給子元件.class one extends react.component render class two extends react.co...
React 狀態提公升
假設我們有這樣乙個需求,提供兩個輸入框 分別屬於兩個元件 保證輸入框裡面的內容同步 下面我們先來封裝乙個輸入框元件 input class input extends react.component this.handlechange this.handlechange.bind this hand...
React 狀態提公升2 6
react中的狀態提公升概括來說,就是將多個元件需要共享的狀態提公升到它們最近的父元件上.在父元件上改變這個狀態然後通過props分發給子元件.列入官網的溫度計算的demo 先寫入乙個溫度輸入元件 class temperatureinput extends react.component hand...