国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

React專題:可變狀態(tài)

hosition / 2802人閱讀

摘要:的參數(shù)既可以是一個(gè)對(duì)象,也可以是一個(gè)回調(diào)函數(shù)。回調(diào)函數(shù)提供了兩個(gè)參數(shù),第一個(gè)參數(shù)就是計(jì)算過(guò)的對(duì)象,即便這時(shí)還沒(méi)有渲染,得到的依然是符合直覺(jué)的計(jì)算過(guò)的值。專題一覽什么是可變狀態(tài)不可變屬性生命周期組件事件操作抽象

本文是『horseshoe·React專題』系列文章之一,后續(xù)會(huì)有更多專題推出
來(lái)我的 GitHub repo 閱讀完整的專題文章
來(lái)我的 個(gè)人博客 獲得無(wú)與倫比的閱讀體驗(yàn)

React使用一個(gè)特殊的對(duì)象this.state來(lái)管理組件內(nèi)部的狀態(tài)。

然后開(kāi)發(fā)者就可以通過(guò)描述狀態(tài)來(lái)控制UI的表達(dá)。

如何描述狀態(tài)呢?

一般我們會(huì)在constructor生命周期鉤子初始化狀態(tài)。

import React, { Component } from "react";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = { name: "", star: 0 };
    }
}

export default App;

也可以直接用屬性初始化器的寫法,看起來(lái)更加簡(jiǎn)潔。

然后通過(guò)this.setSatate()來(lái)改變狀態(tài)。

import React, { Component } from "react";

class App extends Component {
    state = { name: "", star: 0 };
    
    componentDidMount() {
        this.setState({ name: "react", star: 1 });
    }
}

export default App;
this.state 首先,改變狀態(tài)有特殊的門路

開(kāi)發(fā)者不能直接改變this.state的屬性,而是要通過(guò)this.setSatate方法。

為什么要這樣設(shè)計(jì)?

可能是為了更加語(yǔ)義化吧,開(kāi)發(fā)者清楚自己在更新?tīng)顟B(tài),而不是像Vue那樣改變于無(wú)形。

不過(guò)別急,我為正在閱讀的你準(zhǔn)備了一個(gè)炸彈:

猜猜下面例子最終渲染出來(lái)的star是多少?

import React, { Component } from "react";

class App extends Component {
    state = { star: 0 };
    
    componentDidMount() {
        this.state.star = 1000;
        this.setState(prevState => ({ star: prevState.star + 1 }));
    }
    
    // componentDidMount() {
        // this.setState(prevState => ({ star: prevState.star + 1 }));
        // this.state.star = 1000;
    // }
    
    // componentDidMount() {
        // this.state.star = 1000;
        // this.setState({ star: this.state.star + 1 });
    // }
    
    // componentDidMount() {
        // this.setState({ star: this.state.star + 1 });
        // this.state.star = 1000;
    // }
}

export default App;

答案是1001。

誒,不是說(shuō)不能直接改變this.state的屬性么?

聽(tīng)我講,首先,this.state并不是一個(gè)不可變對(duì)象,你(非得較勁的話)是可以直接改變它的屬性的。但是它不會(huì)觸發(fā)render生命周期鉤子,也就不會(huì)渲染到UI上。

不過(guò),既然你確實(shí)改變了它的值,如果之后調(diào)用了this.setSatate()的話,它會(huì)在你直接改變的值的基礎(chǔ)上再做更新。

所以呀少年,要想不懵逼,得靠我們自己的代碼規(guī)范。

至于注釋的部分,只是為了說(shuō)明順序問(wèn)題。

第一部分注釋渲染出來(lái)的star是1001。因?yàn)榛卣{(diào)會(huì)首先計(jì)算star的值,而這時(shí)候star的值是1000。

第二部分注釋渲染出來(lái)的star是1001。這很好理解。

第三部分注釋渲染出來(lái)的star是1。這也好理解,這個(gè)時(shí)候star的值還是0。

其次,狀態(tài)更新會(huì)合并處理

大家也看到了,我們可以每次更新部分狀態(tài)。

新?tīng)顟B(tài)并不會(huì)覆蓋舊狀態(tài),而是將已有的屬性進(jìn)行合并操作。如果舊狀態(tài)沒(méi)有該屬性,則新建。

這類似于Object.assign操作。

而且合并是淺合并。

只有第一層的屬性才會(huì)合并,更深層的屬性都會(huì)覆蓋。

import React, { Component } from "react";

class App extends Component {
    state = { userInfo: { name: "", age: 0 } };
    
    componentDidMount() {
        this.setState({ userInfo: { age: 13 } });
    }
}

export default App;
最后,可以有不是狀態(tài)的狀態(tài)

如果你需要存儲(chǔ)某種狀態(tài),但是不希望在狀態(tài)更新的時(shí)候觸發(fā)render生命周期鉤子,那么完全可以直接存儲(chǔ)到實(shí)例的屬性上,只要不是this.state的屬性。使用起來(lái)還是很自由的。

異步更新 什么叫異步更新?

異步更新說(shuō)的直白點(diǎn)就是批量更新。

它不是真正的異步,只是React有意識(shí)的將狀態(tài)攢在一起批量更新。

React組件有自己的生命周期,在某兩個(gè)生命周期節(jié)點(diǎn)之間做的所有的狀態(tài)更新,React會(huì)將它們合并,而不是立即觸發(fā)UI渲染,直到某個(gè)節(jié)點(diǎn)才會(huì)將它們合并的值批量更新。

以下,組件更新之后this.state.star的值是1。

import React, { Component } from "react";

class App extends Component {
    state = { star: 0 };
    
    componentDidMount() {
        this.setState({ star: this.state.star + 1 });
        this.setState({ star: this.state.star + 1 });
        this.setState({ star: this.state.star + 1 });
    }
}

export default App;

因?yàn)檫@些狀態(tài)改變的操作都是在組件掛載之后、組件更新之前,所以實(shí)際上它們并沒(méi)有立即生效。

this.state.star的值一直是0,盡管狀態(tài)被多次操作,它得到的值一直是1,因此合并之后this.state.star的還是1,并不是我們直覺(jué)以為的3。

為什么要異步更新?

因?yàn)?b>this.setSatate()會(huì)觸發(fā)render生命周期鉤子,也就會(huì)運(yùn)行組件的diff算法。如果每次setState都要走這一套流程,不僅浪費(fèi)性能,而且是完全沒(méi)有必要的。

所以React選擇了在一定階段內(nèi)批量更新。

還是以生命周期為界,掛載之前的所有setState批量更新,掛載之后到更新之前的所有setState批量更新,每次更新間隙的所有setState批量更新。

非異步情況

再來(lái)看一種情況:

猜猜最終渲染出來(lái)的star是多少?

import React, { Component } from "react";

class App extends Component {
    state = { star: 0 };
    timer = null;
    
    componentDidMount() {
        this.timer = setTimeout(() => {
            this.setState({ num: this.state.star + 1 });
            this.setState({ num: this.state.star + 1 });
            this.setState({ num: this.state.star + 1 });
        }, 5000);
    }
    
    componentWillUnmount() {
        clearTimeout(this.timer);
    }
}

export default App;

答案是3。

臥槽!

說(shuō)實(shí)話,這里我也沒(méi)想明白。

我在React倉(cāng)庫(kù)的Issues里提過(guò)這個(gè)情況,這是React主創(chuàng)之一Dan Abramov的回答:

setState is currently synchronous outside of event handlers. That will likely change in the future.

Dan Abramov所說(shuō)的event handlers應(yīng)該指的是React合成事件回調(diào)和生命周期鉤子。

我的理解,因?yàn)橹挥羞@些方法才能回應(yīng)事件,所以它們之中的狀態(tài)更新是批量的。但是它們之中的異步代碼里有狀態(tài)更新操作,React就不會(huì)批量更新,而是符合直覺(jué)的樣子。

我們看下面的例子,正常的重復(fù)setState只會(huì)觸發(fā)一次更新,但是http請(qǐng)求回調(diào)中的重復(fù)setState卻會(huì)多次觸發(fā)更新,看來(lái)異步的setState不在React掌控之內(nèi)。

import React, { Component } from "react";

class App extends Component {
    state = { star: 0 };
    
    componentDidMount() {
        fetch("https://api.github.com/users/veedrin/repos")
            .then(res => res.json())
            .then(res => {
                console.log(res);
                this.setState({ star: this.state.star + 1 });
                this.setState({ star: this.state.star + 1 });
                this.setState({ star: this.state.star + 1 });
            });
    }
}

export default App;

還有一種情況就是原生的事件回調(diào),比如document上的事件回調(diào),也不是異步的。

總結(jié)一下:所謂的異步只是批量更新而已。真正異步回調(diào)和原生事件回調(diào)中的setState不是批量更新的。

不過(guò),Dan Abramov早就提到過(guò),會(huì)在將來(lái)的某個(gè)版本(可能是17大版本)管理所有的setState,不管是不是在所謂的event handlers之內(nèi)。

React的設(shè)計(jì)有一種簡(jiǎn)潔之美,從這種對(duì)待開(kāi)發(fā)者反饋的態(tài)度可見(jiàn)一斑。

回調(diào)

既然this.setSatate()的設(shè)計(jì)不符合直覺(jué),React早就為開(kāi)發(fā)者提供了解決方案。

this.setSatate()的參數(shù)既可以是一個(gè)對(duì)象,也可以是一個(gè)回調(diào)函數(shù)。函數(shù)返回的對(duì)象就是要更新的狀態(tài)。

回調(diào)函數(shù)提供了兩個(gè)參數(shù),第一個(gè)參數(shù)就是計(jì)算過(guò)的state對(duì)象,即便這時(shí)還沒(méi)有渲染,得到的依然是符合直覺(jué)的計(jì)算過(guò)的值。同時(shí),貼心的React還為開(kāi)發(fā)者提供了第二個(gè)參數(shù),雖然并沒(méi)有什么卵用。

以下,組件更新之后this.state.star的值是3。

有一個(gè)小細(xì)節(jié):箭頭函數(shù)如果直接返回一個(gè)對(duì)象,要包裹一層小括號(hào),以區(qū)別塊級(jí)作用域。

import React, { Component } from "react";

class App extends Component {
    state = { star: 0 };
    
    componentDidMount() {
        this.setState((prevState, prevProps) => ({ star: prevState.star + 1 }));
        this.setState((prevState, prevProps) => ({ star: prevState.star + 1 }));
        this.setState((prevState, prevProps) => ({ star: prevState.star + 1 }));
    }
}

export default App;
chaos

總之呢,React更新?tīng)顟B(tài)的設(shè)計(jì)到處都是坑。

大家對(duì)React吐槽最多的點(diǎn)是什么呢?

圈外人吐槽JSX。

圈內(nèi)人吐槽this.setState

期盼React給開(kāi)發(fā)者一個(gè)不令人困惑的狀態(tài)更新API吧。

React專題一覽

什么是UI
JSX
可變狀態(tài)
不可變屬性
生命周期
組件
事件
操作DOM
抽象UI

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/108402.html

相關(guān)文章

  • React專題:不可變屬性

    摘要:沒(méi)有團(tuán)伙,單獨(dú)作案,干凈利落,便于封口。它最大的特點(diǎn)就是不可變。兄弟組件之間傳值原理和回調(diào)函數(shù)一樣,只不過(guò)這里父組件只是一個(gè)橋梁。父組件接收到回調(diào)函數(shù)的值以后,通過(guò)保存該值,并觸發(fā)另一個(gè)子組件重新渲染,重新渲染后另一個(gè)子組件便可以獲得該值。 本文是『horseshoe·React專題』系列文章之一,后續(xù)會(huì)有更多專題推出來(lái)我的 GitHub repo 閱讀完整的專題文章來(lái)我的 個(gè)人博客 ...

    biaoxiaoduan 評(píng)論0 收藏0
  • React專題:什么是UI

    摘要:現(xiàn)代前端框架的使命就是開(kāi)發(fā)者管理狀態(tài),框架根據(jù)狀態(tài)自動(dòng)生成。專題一覽什么是可變狀態(tài)不可變屬性生命周期組件事件操作抽象 本文是『horseshoe·React專題』系列文章之一,后續(xù)會(huì)有更多專題推出來(lái)我的 GitHub repo 閱讀完整的專題文章來(lái)我的 個(gè)人博客 獲得無(wú)與倫比的閱讀體驗(yàn) 什么是UI? 如果你指的是布局和色彩,那更偏向于設(shè)計(jì)師的工作。 在現(xiàn)代web領(lǐng)域,大家已經(jīng)有一個(gè)共識(shí)...

    silvertheo 評(píng)論0 收藏0
  • React專題:生命周期

    摘要:而生命周期鉤子,就是從生到死過(guò)程中的關(guān)鍵節(jié)點(diǎn)。異步渲染下的生命周期花了兩年時(shí)間祭出渲染機(jī)制。目前為這幾個(gè)生命周期鉤子提供了別名,分別是將只提供別名,徹底廢棄這三個(gè)大活寶。生命周期鉤子的最佳實(shí)踐是在這里初始化。 本文是『horseshoe·React專題』系列文章之一,后續(xù)會(huì)有更多專題推出來(lái)我的 GitHub repo 閱讀完整的專題文章來(lái)我的 個(gè)人博客 獲得無(wú)與倫比的閱讀體驗(yàn) 生命周期...

    Hanks10100 評(píng)論0 收藏0
  • React專題react,redux以及react-redux常見(jiàn)一些面試題

    摘要:我們可以為元素添加屬性然后在回調(diào)函數(shù)中接受該元素在樹(shù)中的句柄,該值會(huì)作為回調(diào)函數(shù)的第一個(gè)參數(shù)返回。使用最常見(jiàn)的用法就是傳入一個(gè)對(duì)象。單向數(shù)據(jù)流,比較有序,有便于管理,它隨著視圖庫(kù)的開(kāi)發(fā)而被概念化。 面試中問(wèn)框架,經(jīng)常會(huì)問(wèn)到一些原理性的東西,明明一直在用,也知道怎么用, 但面試時(shí)卻答不上來(lái),也是挺尷尬的,就干脆把react相關(guān)的問(wèn)題查了下資料,再按自己的理解整理了下這些答案。 reac...

    darcrand 評(píng)論0 收藏0
  • react進(jìn)階漫談

    摘要:父組件向子組件之間非常常見(jiàn),通過(guò)機(jī)制傳遞即可。我們應(yīng)該聽(tīng)說(shuō)過(guò)高階函數(shù),這種函數(shù)接受函數(shù)作為輸入,或者是輸出一個(gè)函數(shù),比如以及等函數(shù)。在傳遞數(shù)據(jù)的時(shí)候,我們可以用進(jìn)一步提高性能。 本文主要談自己在react學(xué)習(xí)的過(guò)程中總結(jié)出來(lái)的一些經(jīng)驗(yàn)和資源,內(nèi)容邏輯參考了深入react技術(shù)棧一書以及網(wǎng)上的諸多資源,但也并非完全照抄,代碼基本都是自己實(shí)踐,主要為平時(shí)個(gè)人學(xué)習(xí)做一個(gè)總結(jié)和參考。 本文的關(guān)鍵...

    neuSnail 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<