狀態提升知識點理解
本章節大喵將帶着大家,來梳理React組件數據的狀態提升,做一些簡單的測試研究的歸納總結;首先我們需要來了解一下,變量提升是一個什麼樣的東東?好,我們接着往下看,
就是如果兩個子組件A和B,需要利用到對方的狀態的話,那麼這個時候我們就需要使用到狀態提升,具體的做法就是把A、B兩個子組件的狀態寫到它們的父組件C當中,然後父組件C把狀態傳遞到子組件A和B的props中去,這樣子組件A和B也相當於有狀態,父組件C也就相當於是數據源。
如果還不理解,請看如下解釋:
在react中是單向數據流的設計, 即 只有父組件可以傳遞數據給子組件,而沒有子組件傳遞數據給父組件的概念,也就是主人與僕人的關係。
那麼子組件要傳遞數據給父組件該如何溝通呢?
換句話說就是, react 如何將子組件的值暴露讓父組件獲取到?
可以採用一種迂迴的方法, 在父組件中設置一個方法(函數), 將其通過props傳遞給子組件, 然後在子組件中更新state的狀態,並調用父組件中傳過來的方法, 將state數據作爲參數傳遞給父組件. 這樣, 改變父組件的狀態,從而改變受父組件控制的所有子組件的狀態. 這就是狀態提升的概念. 用官方的原話就是: 共享 state
(狀態) 是通過將其移動到需要它的組件的最接近的共同祖先組件來實現的。 這被稱爲“狀態提升(Lifting State Up)
;
舉例說明
1、先寫一個溫度輸入子組件:
class TemperatureInput extends React.Component {
state = {
temperature: ''
};
handleChange = (e) => {
this.setState({
temperature : e.target.value
})
};
render() {
return (
<fieldset>
<legend>輸入{scaleNames[this.props.scale]}:</legend>
<input type="number" value={this.state.temperature} onChange={this.handleChange}
</fieldset>
)
}
}
2、我們再接着寫另外一個父組件:
class Calculator extends React.Component {
render () {
return (
<div>
<TemperatureInput scale='c'/>
<TemperatureInput scale='f'/>
</div>
)
}
}
上面的父組件和子組件,現在沒有什麼存在的價值,我們僅僅是給兩個溫度輸入組件提供一個父組件,以便我們進行後續的狀態提升。
交互需求:
我們可以輸入攝氏度和華氏度,但是我們現在想要讓這兩個溫度保持一致,就是我們如果輸入攝氏度,那麼下面的華氏度可以自動算出來,如果我們輸入華氏度,那麼攝氏度就可以自動算出來。
那麼我們按照現在這種結構的話,是非常難以實現的,因爲我們知道這兩個組件之間沒有任何關係,它們之間是不知道對方的存在,所以我們需要把它們的狀態進行提升,提升到它們的父組件當中。
3、變量提升改造:首先把子組件(溫度輸入組件)的狀態(state
)全部刪除,看看是什麼樣子:
class TemperatureInput extends React.Component {
handleChange = (e) => {};
render() {
return (
<fieldset>
<legend>輸入{scaleNames[this.props.scale]}:</legend>
<input type="number" value={this.props.temperature} onChange={this.handleChange}/>
</fieldset>
)
}
}
4、變量提升改造:我們通過給 溫度輸入組件 傳入某個函數來讓 溫度輸入組件 中的input
發生變化的時候調用
class TemperatureInput extends React.Component {
handleChange = (e) => {
this.props.onTemperatureChange(e.target.value);
};
render() {
return (
<fieldset>
<legend>輸入{scaleNames[ this.props.scale ]}:</legend>
<input type="number" value={ this.props.temperature } onChange={ this.handleChange } />
</fieldset>
)
}
}
ok,我們的子組件差不多就是這樣了,當然我們也可以省略那個handleChange
函數,我們完全把input
的onChange
這麼寫onChange={this.props.onTemperatureChange}
,這麼寫的話注意onTemperatrueChange
函數的參數是那個事件event
,而不是我這裏寫的 e.target.value
。
5、變量提升改造:修改父組件,補上state
,以及子組件對應的onChange
處理方法,以及子組件的值
class Calculator extends React.Component {
state = {
celsius: '',
fahrenheit: ''
};
onCelsiusChange = (value) => {
this.setState({
celsius: value,
fahrenheit: tryConvert(value, toFahrenheit)
});
};
onFahrenheitChange = (value) => {
this.setState({
celsius: tryConvert(value, toCelsius),
fahrenheit: value
});
};
render() {
return (
<div>
<TemperatureInput scale='c' temperature={this.state.celsius} onTemperatureChange={this.onCelsiusChange}/>
<TemperatureInput scale='f' temperature={this.state.fahrenheit} onTemperatureChange={this.onFahrenheitChange}/>
</div>
)
}
}
這裏我們省略的攝氏度與華氏度的轉換函數,最後加上我們的 水是否能夠燒開的組件。