在React開發中遇到了一個問題:
需求是在一個選擇組件中選擇數據mydata
數組,確定后將mydata
數組返回到父組件,再次打開該選擇組件時,從父組件獲取之前選擇的數據mydata
並顯示為已選擇。
/* 打開選擇組件 */
showModal = () => {
this.setState({
comVisible: true
});
const { mydata } = this.props;
this.setState({
mydata: mydata
});
console.log(this.state.mydata);
this.onChange();
}
/* 確定-將data返回父組件 */
handleOk = () => {
if (this.state.mydata.length > 0) {
this.setState({
comVisible: false
});
// 返回父組件data
this.props.getMyData({
mydata: this.state.mydata,
...
});
} else {
message.error("data is null");
}
}
/* 取消-不對data做操作 */
handleCancel = () => {
this.setState({
comVisible: false
});
}
/* 選擇data */
onChange = (mydata) => {
let mydata = this.state.mydata;
Object.keys(otherdata).forEach((title) => {
...
// 對mydata做一些改變
});
this.setState({
mydata
});
}
大概流程如下:
按照邏輯,在選擇組件中選擇mydata
,觸發onChange
事件,將此時改變的mydata
設置為state.mydata
,點擊確定后觸發handleOk
函數,將state.mydata
傳給父組件。但若點擊取消,則觸發handleCancel
,不做任何操作。
那么問題來了,我點擊了取消,再次打開選擇組件,從父組件取mydata
的值,取到的是點擊取消之前選擇的mydata
值。按理說點擊了取消不做操作,該值是不會傳給父組件的,但是為什么從父組件會取到改變后的值呢?
經過一系列嘗試后發現,問題的原因在於數組的表現形式就是內存中的一段連續的內存地址,數組名稱其實就是連續內存地址的首地址。在onChange
中對mydata
和state.mydata
的改變會直接改變該數組所指向的地址中的數據,而父組件中的mydata
也是指向該數組的,所以一旦state.mydata
發生改變,即使不將改變后的mydata
傳給父組件,父組件的mydata
也會改變。
修改:給父組件傳值時使用中間變量,並且數組賦值時,使用先結構再賦值的方式生成新的數組。
/* 打開選擇組件 */
showModal = () => {
this.setState({
comVisible: true
});
const { mydata } = this.props;
this.setState({
mydata: mydata
});
this.onChange();
}
/* 確定-將data返回父組件 */
handleOk = () => {
if (this.state.mydata.length > 0) {
// 返回父組件data,改變后的中間變量
this.props.getMyData({
mydata: this.state.tempdata,
...
});
} else {
message.error("data is null");
}
}
/* 取消-不對data做操作 */
handleCancel = () => {
...
}
/* 選擇data */
onChange = (mydata) => {
// 改變賦值方式
let mydata = [];
mydata.push(...this.state.mydata);
Object.keys(otherdata).forEach((title) => {
...
// 對mydata做一些改變
});
// 使用中間變量,不直接修改state.mydata
this.setState({
tempdata: mydata
});
}
總結:
在JS中,
數組和對象是地址型變量
數組和對象是地址型變量
數組和對象是地址型變量
基礎知識一定時刻記在腦子里。。。