狀態提升知識點案例解析理解

狀態提升知識點理解


本章節大喵將帶着大家,來梳理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函數,我們完全把inputonChange這麼寫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>
            )
        }
    }

這裏我們省略的攝氏度與華氏度的轉換函數,最後加上我們的 水是否能夠燒開的組件。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章