這是我參與更文挑戰的第18天,活動詳情檢視: 更文挑戰
state是私有的。
官方描述:State 與 props 類似,但是 state 是私有的,并且完全受控于目前元件。
解讀
- 官方對state的介紹很重要,我們必須要知道state是私有的,并且完全受控于目前元件。
将函數元件轉換為類元件
- 建立一個同名的類,并且繼承與React.Component.
- 添加一個空的render()方法.
- 将函數體(return(...))移動到render方法中.
- 在render方法中使用this.props代替props.
- 删除剩餘的空函數聲明.
函數元件
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
複制代碼
類元件
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
複制代碼
- 每次更新的時候render函數都會被調用。
向類元件中添加局部state
- 将render方法中的this.props.data轉換為this.state.date.
- 給類添加一個構造函數,并為this.state指派.
- 移出類元素中的date屬性.
将聲明周期方法添加到類元件中
- componentDidMount():元件挂載後開始運作,此處适合開啟定時器。
- componentWillUnMount():元件将要解除安裝的時候運作,此處适合清除定時器。
- 上面的這種方法叫做聲明周期方法。
使用類元件實作計時功能
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()}
}
tick() {
this.setState({
date: new Date()
})
}
componentDidMount() {
this.timerID = setInterval(() => {
this.tick();
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timerID)
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
複制代碼
計時器的執行順序
- 當Clock元件傳遞給ReactDOM.reder後,React會首先調用Clock元件的構造函數,然後初始化state.
- React調用元件的render方法,然後更新DOM進行渲染。
- 當Clock的輸出被插入到DOM中後,開始調用componentDidMount這個生命周期函數,這個生命周期函數中,React向浏覽器設定一個定時器,每隔1秒,調用元件的tick方法。
- 浏覽器每調用一次tick方法,tick方法都會通過setState更新一次狀态,隻要狀态發生了改變,React就會重新調用元件的render方法,然後進行重新渲染,然後更新DOM。
- 一旦Clock元件從DOM中删除,React就會調用生命周期函數componentWillUnmount,然後清除定時器。
正确使用state
- 不要直接修改state,而是需要通過setState.
this.state.comment = 'Hello'; //不行
this.setState({comment: 'Hello'}); //可以
複制代碼
- state的更新可能是異步的.
- 下面的代碼可能無法更新state
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
複制代碼
- 解決上面的問題,可以讓state接收一個函數,這也是setState更新狀态的第二種方式。
// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
複制代碼
- state的更新會被合并。
看下面的例子你就明白了。
constructor(props) {
super(props);
this.state = {
posts: [],
comments: []
};
}
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
}
複制代碼
官方解釋:this.setState({comments}) 完整保留了 this.state.posts, 但是完全替換了 this.state.comments。
這裡官方的解釋非常完善了。
資料是向下流動的
官方描述:元件可以選擇把它的 state 作為 props 向下傳遞到它的子元件中。FormattedDate 元件會在其 props 中接收參數 date,但是元件本身無法知道它是來自于 Clock 的 state,或是 Clock 的 props,還是手動輸入的。
<FormattedDate date={this.state.date} />
複制代碼
function FormattedDate(props) {
return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}
複制代碼
- 這種資料流就是單向資料流,因為state産生的資料隻能影響其子元件,
歡迎大家關注我的專欄,每日用碎片化的時間學習提高自己,加油!