簡體   English   中英

React js 掛鈎 lodash 設置了奇怪的行為

[英]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上的相同數據,但我不明白原因。

這告訴你useruserInfo (或user.carduserInfo.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

您引用的代碼不會發生這種情況,因為useruserInfo指向不同的對象。 我假設在您的真實代碼中,您以不同的方式填充狀態,而不是使用硬編碼的對象文字。

不可能說為什么你最終讓useruserInfo指向同一個對象,因為你沒有向我們展示發生這種情況的代碼,但你必須做一些類似於上面的代碼片段的事情:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM