React中state和props分別是什麼?
整理一下React中關於state和props的知識點。
在任何應用中,資料都是必不可少的。我們需要直接的改變頁面上一塊的區域來使得檢視的重新整理,或者間接地改變其他地方的資料。React的資料是自頂向下單向流動的,即從父元件到子元件中,元件的資料儲存在props
和state
中,這兩個屬性有啥子區別呢?
props
React的核心思想就是元件化思想,頁面會被切分成一些獨立的、可複用的元件。
元件從概念上看就是一個函式,可以接受一個引數作為輸入值,這個引數就是props
,所以可以把props
理解為從外部傳入元件內部的資料。由於React是單向資料流,所以props
用法
假設我們現在需要實現一個列表,根據React元件化思想,我們可以把列表中的行當做一個元件,也就是有這樣兩個元件:<ItemList/>
和<Item/>
。
先看看<ItemList/>
import Item from "./item"; export default class ItemList extends React.Component{ const itemList = data.map(item => <Item item=item />); render(){ return ( {itemList} ) } }
列表的資料我們就暫時先假設是放在一個data
變數中,然後通過map
函式返回一個每一項都是<Item item='資料'/>
的陣列,也就是說這裡其實包含了data.length
個<Item/>
元件,資料通過在元件上自定義一個引數傳遞。當然,這裡想傳遞幾個自定義引數都可以。
在<Item />
中是這樣的:
export default class Item extends React.Component{ render(){ return ( <li>{this.props.item}</li> ) } }
在render
函式中可以看出,元件內部是使用this.props
來獲取傳遞到該元件的所有資料,它是一個物件,包含了所有你對這個元件的配置,現在只包含了一個item
屬性,所以通過this.props.item
來獲取即可。
只讀性
props
經常被用作渲染元件和初始化狀態,當一個元件被例項化之後,它的props
是隻讀的,不可改變的。如果props
在渲染過程中可以被改變,會導致這個元件顯示的形態變得不可預測。只有通過父元件重新渲染的方式才可以把新的props
傳入元件中。
預設引數
在元件中,我們最好為props
中的引數設定一個defaultProps
,並且制定它的型別。比如,這樣:
Item.defaultProps = {
item: 'Hello Props',
};
Item.propTypes = {
item: PropTypes.string,
};
關於propTypes
,可以宣告為以下幾種型別:
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
注意,bool
和func
是簡寫。
這些知識基礎資料型別,還有一些複雜的,附上鍊接:
https://facebook.github.io/react/docs/typechecking-with-proptypes.html
總結
props
是一個從外部傳進元件的引數,主要作為就是從父元件向子元件傳遞資料,它具有可讀性和不變性,只能通過外部元件主動傳入新的props
來重新渲染子元件,否則子元件的props
以及展現形式不會改變。
state
state
是什麼呢?
State is similar to props, but it is private and fully controlled by the component.
一個元件的顯示形態可以由資料狀態和外部引數所決定,外部引數也就是props
,而資料狀態就是state
。
用法
export default class ItemList extends React.Component{
constructor(){
super();
this.state = {
itemList:'一些資料',
}
}
render(){
return (
{this.state.itemList}
)
}
}
首先,在元件初始化的時候,通過this.state
給元件設定一個初始的state
,在第一次render
的時候就會用這個資料來渲染元件。
setState
state
不同於props
的一點是,state
是可以被改變的。不過,不可以直接通過this.state=
的方式來修改,而需要通過this.setState()
方法來修改state
。
比如,我們經常會通過非同步操作來獲取資料,我們需要在didMount
階段來執行非同步操作:
componentDidMount(){
fetch('url')
.then(response => response.json())
.then((data) => {
this.setState({itemList:item});
}
}
當資料獲取完成後,通過this.setState
來修改資料狀態。
當我們呼叫this.setState
方法時,React會更新元件的資料狀態state
,並且重新呼叫render
方法,也就是會對元件進行重新渲染。
注意:通過this.state=
來初始化state
,使用this.setState
來修改state
,constructor
是唯一能夠初始化的地方。
setState
接受一個物件或者函式作為第一個引數,只需要傳入需要更新的部分即可,不需要傳入整個物件,比如:
export default class ItemList extends React.Component{
constructor(){
super();
this.state = {
name:'axuebin',
age:25,
}
}
componentDidMount(){
this.setState({age:18})
}
}
在執行完setState
之後的state
應該是{name:'axuebin',age:18}
。
setState
還可以接受第二個引數,它是一個函式,會在setState
呼叫完成並且元件開始重新渲染時被呼叫,可以用來監聽渲染是否完成:
this.setState({
name:'xb'
},()=>console.log('setState finished'))
總結
state
的主要作用是用於元件儲存、控制以及修改自己的狀態,它只能在constructor
中初始化,它算是元件的私有屬性,不可通過外部訪問和修改,只能通過元件內部的this.setState
來修改,修改state
屬性會導致元件的重新渲染。
區別
-
state
是元件自己管理資料,控制自己的狀態,可變; -
props
是外部傳入的資料引數,不可變; - 沒有
state
的叫做無狀態元件,有state
的叫做有狀態元件; - 多用
props
,少用state
。也就是多寫無狀態元件。