[英]React js hooks lodash set strange behaviour
我使用 lodash 能夠將屬性(對象、數組)的值更改為一定深度,但我有一個奇怪的行為。
情況是這樣的,我使用帶有鈎子的 react js,在我有一個保存用戶信息的對象的狀態下,我做了一個 fetch 來加載處於名為user
狀態的對象上的用戶信息。
但是,此信息不僅保存在user
對象中,還保存在另一個名為userInfo
對象中,因此我有此信息處於狀態兩次但具有不同的主格屬性。
什么我需要兩次這個信息,只是為了確保當用戶想要更改他們的數據(個人資料頁面)時,我檢查他修改的數據是否真的被修改了,即至少有一個元素不同從原來的。
問題是,當我依次編輯user
上的數據時,它會更改userInfo
上的相同數據,但我不明白原因。
最奇怪的是,這個問題只發生在我工作的本地項目中,在 codeandbox 上做了一個簡單的例子,這個問題沒有發生。
問題似乎是由於handleChangeField
函數引起的,但我不明白為什么只有本地發生。
你能幫我嗎?
鏈接:代碼沙盒
代碼:
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import ReactJson from "react-json-view";
import lodash from "lodash";
const useStyles = makeStyles(theme => ({
root: {
"& > *": {
margin: theme.spacing(1),
width: 200
}
}
}));
export default function BasicTextFields() {
const classes = useStyles();
const [state, setState] = React.useState({
user: {
name: "James",
surname: "bond",
card: {
id: 7,
group: "J"
},
scope: [{ scope: "user", actions: ["create", "delete"] }]
},
userInfo: {
name: "James",
surname: "bond",
card: {
id: 7,
group: "J"
},
scope: [{ scope: "user", actions: ["create", "delete"] }]
}
});
const handleChangeField = field => ({ target: { value } }) => {
let newState = lodash.cloneDeep(state);
lodash.set(newState, field, value);
console.log(newState, state);
setState(newState);
};
console.log("Change", state);
return (
<form className={classes.root} noValidate autoComplete="off">
<ReactJson
src={state}
theme={"solarized"}
enableClipboard={false}
displayObjectSize={false}
/>
<TextField
id="standard-basic"
label="Name"
onChange={handleChangeField("user.name")}
/>
<TextField
id="standard-basic"
label="Group"
onChange={handleChangeField("user.card.group")}
/>
<TextField
id="standard-basic"
label="Action[0]"
onChange={handleChangeField("user.scope[0].actions[0]")}
/>
</form>
);
}
問題是,當我依次編輯
user
上的數據時,它會更改userInfo
上的相同數據,但我不明白原因。
這告訴你user
和userInfo
(或user.card
和userInfo.card
)在它發生的情況下指的是同一個對象:
const userDataFromAjaxOrWhatever = { name: "James", surname: "bond", card: { id: 7, group: "J" }, scope: [{ scope: "user", actions: ["create", "delete"] }] }; const state = { user: userDataFromAjaxOrWhatever, userInfo: userDataFromAjaxOrWhatever }; console.log(`state.user.name = ${state.user.name}`); console.log(`state.userInfo.name = ${state.userInfo.name}`); console.log("Setting state.user.name = Joe"); state.user.name = "Joe"; console.log(`state.user.name = ${state.user.name}`); // Joe console.log(`state.userInfo.name = ${state.userInfo.name}`); // Joe
您引用的代碼不會發生這種情況,因為user
和userInfo
指向不同的對象。 我假設在您的真實代碼中,您以不同的方式填充狀態,而不是使用硬編碼的對象文字。
不可能說為什么你最終讓user
和userInfo
指向同一個對象,因為你沒有向我們展示發生這種情況的代碼,但你必須做一些類似於上面的代碼片段的事情:
const state = {
user: userDataFromAjaxOrWhatever,
userInfo: userDataFromAjaxOrWhatever
};
反而:
const state = {
user: userDataFromAjaxOrWhatever,
userInfo: lodash.cloneDeep(userDataFromAjaxOrWhatever)
};
那你就沒有這個問題了:
const userDataFromAjaxOrWhatever = { name: "James", surname: "bond", card: { id: 7, group: "J" }, scope: [{ scope: "user", actions: ["create", "delete"] }] }; const state = { user: userDataFromAjaxOrWhatever, userInfo: _.cloneDeep(userDataFromAjaxOrWhatever) }; console.log(`state.user.name = ${state.user.name}`); console.log(`state.userInfo.name = ${state.userInfo.name}`); console.log("Setting state.user.name = Joe"); state.user.name = "Joe"; console.log(`state.user.name = ${state.user.name}`); // Joe console.log(`state.userInfo.name = ${state.userInfo.name}`); // James
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.