state 為自身component 存放資料的地方,管理內部狀態,格式為一個物件,以class component來說,在建立自身的component state之前記得在constructor要先呼叫super(),不然會取不到this
如果沒執行super ,就調用this, 畫面會直接報錯提醒你
如果是create react app的話不需要寫constructor了,因為已經引用了@babel/plugin-proposal-class-properties套件,可以直接寫state,但因為練習的關係,接下來的範例還是會乖乖寫constructor
這是省去constructor的寫法
class StateExample extends Component{
state = {
count:0 //初始值
}
}
利用this.state.count就可以取到值,用setState可以改變state
setState傳入兩個參數 第一個是物件,第二個是callback function
利用setState來改變原本的state,記得要傳入的是一個物件,當state偵測到資料更動的時候就會觸發render讓畫面重新渲染。
class StateExample extends Component{
constructor(){
super()
this.state = {
count:0 //初始值
}
}
addCount = () => {
let num = this.state.count + 1
this.setState({ count: num}) //改變state
}
render(){
return(
<Fragment>
<h1>{this.state.count}</h1>
<button onClick={this.addCount}>add</button>
</Fragment>
)
}
}
如果我不用setState , 直接改state的值呢?你就會發現畫面一動也不動,因為React並不知道state已經被修改了,所以一定要用setState!
addCount = () => {
this.state.count++
}
//這樣是不會有反應的
另外,我在官網看到一個蠻有趣的例子,試著實作一下,點了按鈕後會連續觸發三次+1的function,預期應該會在畫面上看到3這個數字,結果,居然數字只有1!原來會造成這樣的原因是setState是非同步的,如果要解決這樣的問題該怎麼做?
handleClick = () =>{
this.addCount()
this.addCount()
this.addCount()
}
可以傳入一個更新用的function讓你可以取到當前state,而非舊的state
addCount = () => {
this.setState((state)=>({ count: state.count + 1}))
}
props 為子組件接受父組件的溝通管道,是唯獨的不可異動
父組件利用title屬性傳入值
<PropsExample title='member center' />
子組件用props取的上面傳下來的title
class PropsExample extends Component{
constructor(){
super()
}
render() {
return (
<Fragment>
<h1>{this.props.title}</h1>
</Fragment>
)
}
}
假設我試圖想要從子組件改變this.props.title
return (
<Fragment>
<h1>{this.props.title}</h1>
<button onClick={()=>{this.props.title='record'}}>change</button>
</Fragment>
)
就會報錯了!告訴你這是個唯獨的值,因此想要改動的話,還是乖乖從父組件異動吧!或者將setState的方法透過props丟給子組件,讓子組件呼叫也是可以達成修改props的目的
另外再傳入props的時候,也可以順便定義一下型別,確保收到的props是正確的,React.PropTypes已經被棄用了,目前官網建議安裝prop-types來檢查型別
import PropTypes from 'prop-types';
class PropsExample extends Component{
constructor(){
super()
}
render() {
return (
<Fragment>
<h1>{this.props.title}</h1>
</Fragment>
)
}
}
PropsExample.propTypes = {
title:PropTypes.string
}
假設我故意傳數字進來,就會報錯了
另外還有一種寫法可以傳入各種元素進去,乍看還蠻像vue的slot(雖然兩個功能不太一樣啦..
class PropsExample extends Component {
constructor() {
super()
}
render() {
return (
this.props.children
)
}
}
父組件的結構如下
<PropsExample>
<ul>
<li>apple</li>
<li>banana</li>
<li>lemon</li>
</ul>
</PropsExample>
就能將< PropsExample >標籤內的html當作props丟給子組件接收了
以上就是關於State和props的簡單介紹!