作者:墨成
React版本 :16.4.1
仔細(xì)閱讀官網(wǎng)setState的描述會(huì)發(fā)現(xiàn)里面透露的信息量巨大,我也建議初學(xué)者在學(xué)習(xí)React之前仔細(xì)閱讀原始文檔,以下是我個(gè)人在閱讀文檔時(shí)的一些領(lǐng)悟,配合了一些翻譯和講解,限于個(gè)人水平,不足之處,各位請(qǐng)多多指出
setState(updater[, callback])
setState()enqueueschanges to the component state and tells React that this component and itschildren need to be re-rendered with the updated state. This is the primarymethod you use to update the user interface in response to event handlers andserver responses.
翻譯:? setState()通過隊(duì)列的形式保存組件狀態(tài)并告訴React這個(gè)組件和他的子組件需要重新渲染。這是我們通過事件或服務(wù)器響應(yīng)更新用戶接口的主要方法(也就是說我們最常用)
解釋:無
Think
of setState()as arequest rather than an immediate command to update the component. For betterperceived performance, React may delay it, and then update several componentsin a single pass. React does not guarantee that the state changes are appliedimmediately.
翻譯: setState()只是作為一個(gè)請(qǐng)求而不是一個(gè)立刻執(zhí)行的指令去更新組件。為了更好的性能,React會(huì)延遲執(zhí)行,然后通過一種單一(這個(gè)單一在這里的意思是歸類的意思)的方式去更新幾個(gè)組件。React不會(huì)立刻把state的改變應(yīng)用到組件上
解釋:這句的話的意思很明顯就是告訴你: React的 setState是"異步"的,React在沒有重新渲染之前對(duì)state的做了一些處理以達(dá)到最佳的性能
setState() does not
always immediately update the component. It may batch or defer the update until
later. This makes reading this.state right
after calling setState() a
potential pitfall. Instead, use componentDidUpdate or a setState callback (setState(updater,
callback)), either of which are guaranteed to fire after the update has
been applied. If you need to set the state based on the previous state, read
about the updaterargumentbelow.
翻譯: setState()并不總是立刻更新組件(言下之意就是有辦法可以立刻更新,后面會(huì)講道這部分內(nèi)容)。隨后它會(huì)使用批處理或延遲更新 。在你調(diào)用setState()后立刻讀取 this.state的值不會(huì)生效(原文叫 潛在的陷阱)。相反,使用componentDidUpdate或者? setState回調(diào)函數(shù) 的任意一種方式都會(huì)讓對(duì)state的更新生效(原文的作者使用了fire這個(gè)詞非常形象,想象一下這樣的一種場(chǎng)景:你為了一個(gè)難題徹夜難眠,絞盡腦汁,突然看到了火(黑暗前的黎明,激動(dòng))是希望?。?.如果你想基于上一個(gè)state來設(shè)置state,請(qǐng)閱讀下方updater的參數(shù)
解釋:setSate雖然是異步的,但是我們還是可以通過其他方式讀取到生效的值,比如在react生命周期函數(shù) componentDidUpdate和 setState的回調(diào)函數(shù)中讀取
。言下之意是告訴我們?cè)?setState完成后,會(huì)激活 componentDidUpdate周期函數(shù),有回調(diào)函數(shù)會(huì)執(zhí)行回調(diào)函數(shù)。
[if !supportLineBreakNewLine]
[endif]
setState() will
always lead to a re-render unless shouldComponentUpdate() returns false. If mutable
objects are being used and conditional rendering logic cannot be implemented in shouldComponentUpdate(), calling setState()only whenthe new state differs from the previous state will avoid unnecessaryre-renders.
翻譯: setState總是會(huì)觸發(fā)重渲染,除非shouldComponentUpdate()返回 false .shouldComponentUpdate()不應(yīng)該包含可變對(duì)象作為條件渲染的邏輯,我們僅僅在state發(fā)生變化去調(diào)用setSate而避免不必要的重新渲染
解釋:shouldComponentUpdate()的邏輯中不可以直接用不穩(wěn)定對(duì)象的值作為返回值,就是說對(duì)于引用類型,地址總是相同,返回值永遠(yuǎn)為true(淺比較).
The
first argument is an updaterfunction with the signature:
(prevState, props) => stateChange
prevState is a
reference to the previous state. It should not be directly mutated. Instead,
changes should be represented by building a new object based on the input from prevStateand props. For instance,
suppose we wanted to increment a value in state by props.step:
翻譯:prevState 是上一個(gè)狀態(tài)的引用.它不應(yīng)該直接被改變。這種變化應(yīng)該是基于prevState和 props構(gòu)建的一個(gè)新對(duì)象。比如,假如我們想在state中通過props.step去對(duì)一個(gè)值做增量操作:
解釋:無
this.setState((prevState, props) => {
? return {counter: prevState.counter + props.step};
});
Both prevState and props received
by the updater function are guaranteed to be up-to-date. The output of the
updater is shallowly merged with prevState.
翻譯: updater
function保證接受到的prevState和props是最新的(這里的最新是相對(duì)于上次 render后的值,而不是連續(xù)調(diào)用setState的值,這里可能會(huì)讓有些人有點(diǎn)誤解)。調(diào)用updater function是淺合并(這里有故事)
解釋:無
The
second parameter to setState() is an
optional callback function that will be executed once setState is
completed and the component is re-rendered. Generally we recommend using componentDidUpdate()for suchlogic instead.
翻譯:第二個(gè)是可選的回調(diào)函數(shù),它會(huì)在setState完成后并且組件重新渲染后立刻執(zhí)行。一般來說,我們推薦使用componentDidUpdate()來替換這個(gè)邏輯。
解釋:如果使用回調(diào)函數(shù),React更建議在componentDidUpdate來處理這個(gè)邏輯。就是這個(gè)回調(diào)函數(shù)在沒有特別必要的情況下不要使用(源碼對(duì)callback做了很多邏輯處理,后面也會(huì)提及)
You
may optionally pass an object as the first argument to setState()instead ofa function:
setState(stateChange[, callback])
翻譯:你可以有選擇性的傳遞一個(gè)對(duì)象作為setState的第一參數(shù)
解釋:除了傳遞函數(shù)之外也可以使用對(duì)象作為參數(shù)
This
performs a shallow merge of stateChangeinto thenew state, e.g., to adjust a shopping cart item quantity:
this.setState({quantity: 2})
翻譯:它會(huì)執(zhí)行淺合并來生成一個(gè)新的state,比如說:修改購物車?yán)锏纳唐窋?shù)量
This
form of setState()is alsoasynchronous, and multiple calls during the same cycle may be batched together.For example, if you attempt to increment an item quantity more than once in thesame cycle, that will result in the equivalent of:
Object.assign(
? previousState,
? {quantity: state.quantity + 1},
? {quantity: state.quantity + 1},
? ...
)
翻譯:這種形式的setState()(把對(duì)象作為參數(shù))也是"異步"的,相同周期(這個(gè)cycle的翻譯我還沒找到合適的詞,暫且使用周期,比如同一個(gè)函數(shù)多次調(diào)用setState,我們就認(rèn)為他們?cè)谕粋€(gè)周期)的多次調(diào)用會(huì)被批量執(zhí)行。比如,如果你試圖在同一周期多次增加商品的數(shù)量,那么它的結(jié)果等同于:
解釋:這里的例子非常關(guān)鍵,要理解它必須完全理解Object.assign合并對(duì)象的原理,比如說,不同對(duì)象相同屬性,后面的對(duì)象會(huì)覆蓋前面的對(duì)象;不同對(duì)象不同屬性,會(huì)合并到最終的對(duì)象上
Subsequentcalls will override values from previous calls in the same cycle, so thequantity will only be incremented once. If the next state depends on the previousstate, we recommend using the updater function form, instead:
this.setState((prevState) => {
? return {quantity: prevState.quantity + 1};
});
翻譯:在同一周期靠后的setState()將會(huì)覆蓋前一個(gè)setSate()的值(相同屬性名),因此,這個(gè)商品數(shù)量僅自增了一次,如果希望下一個(gè)state依賴上一個(gè)state,我們推薦使用函數(shù)的形式
解釋:這里很明顯的告訴我們,setSate第一參數(shù)傳遞的對(duì)象或函數(shù),react的處理方式不一樣, 這跟React在性能優(yōu)化有很大關(guān)系,為了最小可能性去re-render(重渲染),React源碼作了很多額外的工作
至此,官方文檔對(duì)setState()的概要描述已經(jīng)結(jié)束
后面我會(huì)對(duì)官方的文檔的解釋寫一些demo來驗(yàn)證
同時(shí)隨著理解的深入,后面會(huì)不斷對(duì)源碼進(jìn)行解析
未完待續(xù)..........