React?組件中?State?的定義、使用及正確使用方式
前言
在 React 應(yīng)用開發(fā)中,state 是組件內(nèi)部用來(lái)存儲(chǔ)和管理數(shù)據(jù)的關(guān)鍵概念。它允許組件根據(jù)不同的狀態(tài)展示不同的 UI。本文將詳細(xì)介紹 state 的定義、使用方式以及如何正確地更新 state,幫助開發(fā)者更好地理解和運(yùn)用這一核心特性。
1.1 state及其特點(diǎn)
State 與 props 類似,但是 state 是私有的,并且完全受控于當(dāng)前組件
不要直接修改state:構(gòu)造函數(shù)是唯一可以給 this.state 賦值的地方。
state更新可能是異步的:出于性能考慮,React 可能會(huì)把多個(gè) setState() 調(diào)用合并成一個(gè)調(diào)用。
state更新會(huì)被合并:當(dāng)你調(diào)用 setState() 的時(shí)候,React 會(huì)把你提供的對(duì)象合并到當(dāng)前的 state
1.2 state的定義和使用
目前react中的狀態(tài)有兩種使用方式:
1.2.1 es6的類 - 構(gòu)造函數(shù)
src/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
?
// 引入時(shí),后綴名可以省略,可以在webpack中配置
// import App from './01-App-parent-child'
// import App from './02-App-parent-child-value'
// import App from './03-App-parent-child-value-default'
// import App from './04-App-parent-child-value-default-type'
// import App from './05-App-props-children'
// import App from './06-App-mutiple-props-children'
// import App from './07-App-mouse-tracker'
// import App from './08-App-render-props'
import App from './09-App-state-es6'
?
const root = ReactDOM.createRoot(document.getElementById('root'))
?
root.render(<App />)src/09-App-state-es6.jsx
import React, { Component } from 'react';
?
/**
* ES6 規(guī)定,子類必須在constructor()方法中調(diào)用super(),否則就會(huì)報(bào)錯(cuò)。
這是因?yàn)樽宇愖约旱膖his對(duì)象,必須先通過(guò)父類的構(gòu)造函數(shù)完成塑造,
得到與父類同樣的實(shí)例屬性和方法,然后再對(duì)其進(jìn)行加工,添加子類自己的實(shí)例屬性和方法。
如果不調(diào)用super()方法,子類就得不到自己的this對(duì)象。
?
ES5 的繼承機(jī)制,是先創(chuàng)造一個(gè)獨(dú)立的子類的實(shí)例對(duì)象,
然后再將父類的方法添加到這個(gè)對(duì)象上面,即“實(shí)例在前,繼承在后”。
ES6 的繼承機(jī)制,則是先將父類的屬性和方法,加到一個(gè)空的對(duì)象上面,
然后再將該對(duì)象作為子類的實(shí)例,即“繼承在前,實(shí)例在后”
*/
class App extends Component {
// es6的類 - 構(gòu)造函數(shù)
constructor (props) {
super(props) // 調(diào)用父類的constructor(props)
this.state = { // 添加子類自己的實(shí)例屬性和方法,在react中 state作為初始化狀態(tài)的屬性
date: new Date()
}
}
render() {
return (
<div>
現(xiàn)在的時(shí)間是:{ this.state.date.toLocaleDateString() + this.state.date.toLocaleTimeString() }
</div>
);
}
}
?
export default App;1.2.2 es7的類 - 屬性初始化器
src/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
?
// 引入時(shí),后綴名可以省略,可以在webpack中配置
// import App from './01-App-parent-child'
// import App from './02-App-parent-child-value'
// import App from './03-App-parent-child-value-default'
// import App from './04-App-parent-child-value-default-type'
// import App from './05-App-props-children'
// import App from './06-App-mutiple-props-children'
// import App from './07-App-mouse-tracker'
// import App from './08-App-render-props'
// import App from './09-App-state-es6'
import App from './10-App-state-es7'
?
const root = ReactDOM.createRoot(document.getElementById('root'))
?
root.render(<App />)src/10-App-state-es7.jsx
import React, { Component } from 'react';
?
// 推薦寫法
class App extends Component {
state = { // es7 類的屬性
date: new Date()
}
render() {
return (
<div>
現(xiàn)在的時(shí)間是:{ this.state.date.toLocaleDateString() + this.state.date.toLocaleTimeString() }?。?!
</div>
);
}
}
?
export default App;1.3 如何正確的修改state
setState() 將對(duì)組件 state 的更改排入隊(duì)列,并通知 React 需要使用更新后的 state 重新渲染此組件及其子組件。這是用于更新用戶界面以響應(yīng)事件處理器和處理服務(wù)器數(shù)據(jù)的主要方式.
將 setState() 視為請(qǐng)求而不是立即更新組件的命令。為了更好的感知性能,React 會(huì)延遲調(diào)用它,然后通過(guò)一次傳遞更新多個(gè)組件。
setState() 并不總是立即更新組件。它會(huì)批量推遲更新。這使得在調(diào)用 setState() 后立即讀取 this.state 成為了隱患。為了消除隱患,請(qǐng)使用 componentDidUpdate 或者 setState 的回調(diào)函數(shù)(setState(updater, callback)),這兩種方式都可以保證在應(yīng)用更新后觸發(fā)。
記住修改狀態(tài)的三大原則:
不要直接修改 State
state = { a: 10 }
this.state.a = 100 // ?state 的更新可能是異步的
state = { a: 10 }
this.setState({a: this.state.a + 1 })
this.setState({a: this.state.a + 1 })
this.setState({a: this.state.a + 1 })
console.log(this.state.a) // 10state 的更新會(huì)被合并
1.4 this.setState()方法及其特點(diǎn)
setState() 會(huì)對(duì)一個(gè)組件的 state 對(duì)象安排一次更新。當(dāng) state 改變了,該組件就會(huì)重新渲染。
setState()可以添加兩個(gè)參數(shù),
setState() 的第二個(gè)參數(shù)為可選的回調(diào)函數(shù),它將在 setState 完成合并并重新渲染組件后執(zhí)行
1.4.1 傳遞函數(shù)
參數(shù)一為帶有形式參數(shù)的 updater 函數(shù):
this.setState((state, props) => stateChange[, callback] )
src/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
?
// 引入時(shí),后綴名可以省略,可以在webpack中配置
// import App from './01-App-parent-child'
// import App from './02-App-parent-child-value'
// import App from './03-App-parent-child-value-default'
// import App from './04-App-parent-child-value-default-type'
// import App from './05-App-props-children'
// import App from './06-App-mutiple-props-children'
// import App from './07-App-mouse-tracker'
// import App from './08-App-render-props'
// import App from './09-App-state-es6'
// import App from './10-App-state-es7'
import App from './11-App-setState-function'
?
const root = ReactDOM.createRoot(document.getElementById('root'))
?
root.render(<App />)src/11-App-setState-function.jsx
import React, { Component } from 'react';
?
class App extends Component {
state = {
count: 100
}
render() {
return (
<div>
{ this.state.count }
<button onClick={ () => {
this.setState((state, props) => {
console.log(state, props)
return {
count: state.count + 1
}
})
this.setState((state, props) => {
console.log(state, props)
return {
count: state.count + 1
}
})
this.setState((state, props) => {
console.log(state, props)
return {
count: state.count + 1
}
})
} }>加</button>
</div>
);
}
}
?
export default Appupdater 函數(shù)中接收的
state和props都保證為最新。updater 的返回值會(huì)與state進(jìn)行淺合并。
1.4.2 傳遞對(duì)象
src/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
?
// 引入時(shí),后綴名可以省略,可以在webpack中配置
// import App from './01-App-parent-child'
// import App from './02-App-parent-child-value'
// import App from './03-App-parent-child-value-default'
// import App from './04-App-parent-child-value-default-type'
// import App from './05-App-props-children'
// import App from './06-App-mutiple-props-children'
// import App from './07-App-mouse-tracker'
// import App from './08-App-render-props'
// import App from './09-App-state-es6'
// import App from './10-App-state-es7'
// import App from './11-App-setState-function'
import App from './12-App-setState-object'
?
const root = ReactDOM.createRoot(document.getElementById('root'))
?
root.render(<App />)src/12-App-setState-object.jsx
import React, { Component } from 'react';
// 為什么?
// const obj = { a: 100 }
// es6 中對(duì)象合并
// const newObj = Object.assign(obj, {a: 100 + 1}, {a: 100 + 1}, {a: 100 + 1})
// console.log(newObj) // { a: 101 }
?
class App extends Component {
state = {
count: 10
}
render() {
return (
<div>
{ this.state.count }
<button onClick={ () => {
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
this.setState({
count: this.state.count + 1
})
console.log(this.state.count)
} }>加</button>
</div>
);
}
}
?
export default App;這種形式的
setState()是異步的,并且在同一周期內(nèi)會(huì)對(duì)多個(gè)setState進(jìn)行批處理,相當(dāng)于
Object.assign(
prevState,
{count: this.state.count + 1},
{count: this.state.count + 1},
...
)后調(diào)用的
setState()將覆蓋同一周期內(nèi)先調(diào)用setState的值,因此商品數(shù)僅增加一次。如果后續(xù)狀態(tài)取決于當(dāng)前狀態(tài),建議使用 updater 函數(shù)的形式代替(前面案例已經(jīng)實(shí)現(xiàn))?;蛘咴诘诙€(gè)參數(shù)中再繼續(xù)操作。
src/index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
?
// 引入時(shí),后綴名可以省略,可以在webpack中配置
// import App from './01-App-parent-child'
// import App from './02-App-parent-child-value'
// import App from './03-App-parent-child-value-default'
// import App from './04-App-parent-child-value-default-type'
// import App from './05-App-props-children'
// import App from './06-App-mutiple-props-children'
// import App from './07-App-mouse-tracker'
// import App from './08-App-render-props'
// import App from './09-App-state-es6'
// import App from './10-App-state-es7'
// import App from './11-App-setState-function'
// import App from './12-App-setState-object'
import App from './13-App-setState-callback'
?
const root = ReactDOM.createRoot(document.getElementById('root'))
?
root.render(<App />)src/13-App-setState-callback.jsx
import React, { Component } from 'react';
?
?
class App extends Component {
state = {
count: 10
}
render() {
return (
<div>
{ this.state.count }
<button onClick={ () => {
this.setState({
count: this.state.count + 1
}, () => {
this.setState({
count: this.state.count + 1
}, () => {
this.setState({
count: this.state.count + 1
})
})
})
console.log(this.state.count) // 10
} }>加</button>
</div>
);
}
}
?
export default App;思考題:
總結(jié)
通過(guò)本文的介紹,我們了解了 state 在 React 組件中的重要性,以及如何在 ES6 和 ES7 類組件中定義和使用 state。同時(shí),我們還探討了正確更新 state 的方法,包括使用 setState() 方法時(shí)需要注意的事項(xiàng)。遵循這些最佳實(shí)踐,可以幫助我們避免常見的陷阱,提高應(yīng)用的性能和可靠性。
到此這篇關(guān)于React 組件中 State 的定義、使用及正確更新方式的文章就介紹到這了,更多相關(guān)React State 組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React?hook實(shí)現(xiàn)簡(jiǎn)單的websocket封裝方式
這篇文章主要介紹了React?hook實(shí)現(xiàn)簡(jiǎn)單的websocket封裝方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
React實(shí)現(xiàn)點(diǎn)擊切換組件效果
這篇文章主要為大家詳細(xì)介紹了如何基于React實(shí)現(xiàn)點(diǎn)擊切換組件效果,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的小伙伴可以學(xué)習(xí)一下2023-08-08
React之如何在Suspense中優(yōu)雅地請(qǐng)求數(shù)據(jù)
Suspense 是 React 中的一個(gè)組件,直譯過(guò)來(lái)有懸掛的意思,能夠?qū)⑵浒漠惒浇M件掛起,直到組件加載完成后再渲染,本文詳細(xì)介紹了如何在Suspense中請(qǐng)求數(shù)據(jù),感興趣的小伙伴可以參考閱讀本文2023-04-04
react中的useImperativeHandle()和forwardRef()用法
這篇文章主要介紹了react中的useImperativeHandle()和forwardRef()用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
React利用props的children實(shí)現(xiàn)插槽功能
React中并沒(méi)有vue中的?slot?插槽概念?不過(guò)?可以通過(guò)props.children?實(shí)現(xiàn)類似功能,本文為大家整理了實(shí)現(xiàn)的具體方,需要的可以參考一下2023-07-07
react實(shí)現(xiàn)一個(gè)優(yōu)雅的圖片占位模塊組件詳解
這篇文章主要給大家介紹了關(guān)于react如何實(shí)現(xiàn)一個(gè)還算優(yōu)雅的占位模塊圖片組件的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10

