React 部落格系列 (2) React中的state和props更新
阿新 • • 發佈:2018-11-11
React中的state和props更新
github個人部落格原始碼持續更新中。。。
在搭建個人部落格的過程中,需要新增一個登陸窗體,登陸按鈕和登陸表單分別在不同的元件,登陸btn在元件HeaderCustom,登陸窗體和表單在FormLogin,由登陸btn控制FormLogin的顯示和隱藏,利用Redux進行狀態管理。
HeaderCustom
onLogin = () => {
this.setState({
visible: true
},()=>{
console.log("onLogin_state" );
console.log(this.state);
});
}
render(){
return(....
<Menu.Item key="7" className="" style={ { lineHeight: '64px', position: "absolute", right: '0px', top: "0px" } }>
<span onClick={ this.onLogin }> <Icon type="user" style={ { fontSize: 16, color : '#1DA57A' } }/>{ this.props.username } </span>
<UserLoginFrom visible={ loginFormVisible }></UserLoginFrom>
</Menu.Item>
...);
}
const mapStateToProps = (state) => {
var adminAccess = state.reducer_login.adminAccess;
var loginVisible = state.reducer_login.loginFormVisible;
return {
adminAccess: adminAccess,
loginFormVisible: loginVisible
}
}
FormLogin
handleOk = () => {
this._loginCheck()
this.setState({
loading: true
});
setTimeout(() => {
this.setState({
visible: false
});
}, 3000);
this.props.changeLoginVisible({
loginFormVisible:false
})
}
handleCancel() {
this.setState({
visible: false
});
this.props.changeLoginVisible({
loginFormVisible:false
})
}
render() {
const {getFieldDecorator} = this.props.form;
const {visible, loading} = this.state;
return (
<Modal style={ { textAlign: "center" } } destroyOnClose={true} cancelText="取消" okText="登陸" visible={ visible } title="管理端登陸驗證" onOk={ this.handleOk.bind(this) } onCancel={ this.handleCancel.bind(this) }>
<Form onSubmit={ this.handleSubmit } className="login-form">
......
</Form>
</Modal>
);
}
const mapDispatchToProps = (dispatch) => {
return {
changeAccess: (assessToAdmin) => {
dispatch(changeAdminAccess(assessToAdmin))
},
changeLoginVisible:(loginFormVisible)=>{
dispatch(closeUserLoginForm(loginFormVisible))
}
}
}
解決方法1
在實施的過程中,遇到了setState方法和props更新的困擾,由於每次關閉窗體後,傳遞給HeaderCoustom的props為 loginFormVisible:false,出現了再次點選登陸按鈕時窗體不顯示的情況,經過分析才發現,props物件沒有發生改變,render方法當然不會自動執行,故解決的辦法是在props物件中加入時間戳:
const mapStateToProps = (state) => {
var adminAccess = state.reducer_login.adminAccess;
var loginVisible = state.reducer_login.loginFormVisible;
//加入 key:(new Date()).getTime() 時間戳 每次傳入的Props物件都不一樣 元件都會重新渲染一次
return {
adminAccess: adminAccess,
loginFormVisible: loginVisible,
key:(new Date()).getTime()
}
}
在實施的過程中,還發現了setState執行後,state物件不會立馬改變,而是先執行render渲染後,才發生變化的。
onLogin = () => {
this.setState({
visible: true
},()=>{
console.log("onLogin_state");
console.log(this.state);//回撥函式函式在render執行後再觸發,此處列印的是變化後的state
});
console.log(this.state);//列印state變化前的物件
}
解決方法2
放發一用到了redux重新整理父級組價的props,這在深層次的巢狀中是最有效的傳遞狀態的方法,但是在直接巢狀的父子元件中,感覺有些大材小用,父級元件可以直接繫結方法傳遞給子元件。
父級元件
onLoginClose = () => {
this.setState({
visible: false
}, () => {
console.log("onLogin_close");
console.log(this.state);
});
}
render(){
...
<Menu.Item key="7" className="" style={ { lineHeight: '64px', position: "absolute", right: '0px', top: "0px" } }>
<span onClick={ this.onLogin }> <Icon type="user" style={ { fontSize: 16, color: '#1DA57A' } }/>{ this.props.username } </span>
<UserLoginFrom visible={ loginFormVisible } onClose={ this.onLoginClose.bind(this) }></UserLoginFrom>
</Menu.Item>
}
...
子元件
handleCancel() {
this.setState({
visible: false
});
console.log(this.props.onClose)
this.props.onClose();
}
將onClose傳遞給子元件 ,子元件狀態改變時,反饋給父級元件改變父級自身的狀態。