首页 > 解决方案 > 未捕获的类型错误:更新状态时无法分配给只读属性

问题描述

我正在尝试重现我原来的问题。

我有两个处于反应状态Array1的数组,它们是来自数据库的原始数组,并且Array2是处于状态的更新数组。

目标是仅更新已更改rate而不是quantity(和其他属性)回数据库,因此我需要使用数组对象中的速率值更新对象中的basicrecipe速率recipeBasicRecipe值,以匹配 basicrecipe与对象匹配的对象在recipeBasicRecipe.

运行代码时出现此错误,请求帮助

Error:Uncaught TypeError: Cannot assign to read only property

let basicRecipes = [
  {
    id: 1,
    name: IceCream,
    details: [{ id: "12", name: "milk", quantity: "50", rate: "100" },
    { id: "13", name: "cream", quantity: "50", rate: "300" }]
  },
  {
      id: 2,
      name: Coffee,
      details: [{ id: "14", name: "Coffee bean", quantity: "60", rate: "200" },
      { id: "15", name: "water", quantity: "60", rate: "300" }]

  },
  {
      id: 3,
      name: Tea,
      details: [{ id: "16", name: "Tea leaf", quantity: "50", rate: "700"      
      }]
}]


let recipeBasicRecipe = [
  {
      id: 1,
      name: IceCream,
      details: [{ id: "12", name: "milk", quantity: "50", rate: "500" },
      { id: "13", name: "cream", quantity: "50", rate: "700" }]
  },
  {
      id: 2,
      name: Coffee,
      details: [{ id: "14", name: "Coffee bean", quantity: "60", rate: "800" },
      { id: "15", name: "water", quantity: "60", rate: "8000" }]
  }
];

let r = basicRecipe;

let Array2 = recipeBasicRecipes;

r = r.map(item => {
  let element = Array2.find(e => e.id == item.id);
  if (element) {
    item.details = item.details.map(e => {
      let detail = element.details.find(d => d.id == e.id);
      if (detail) {
        e.rate = detail.rate;
      }
      return e;
    });
  }
  return item;
});

console.log(r);
提出相关的反应代码:

const initialState = {

    basicRecipe: [],

    recipeBasicRecipes: [],
   
  };

  const [state, dispatch] = useReducer(recipeManagementReducer, initialState);


我正在执行此代码的功能

  const onSubmit = e => {
    e.preventDefault();
    /**
    * 
    setShowLoader();
    updateawMateris(state.recipeRawMaterials);
    *  */

    let r = state.basicRecipe;

    let Array2 = state.recipeBasicRecipes;

    r = r.map(item => {
      let element = Array2.find(e => e._id == item._id);
      if (element) {
        item.details = item.details.map(e => {
          let detail = element.details.find(d => d._id == e._id);
          if (detail) {
            e.rate = detail.rate;
          }
          return e;
        });
      }
      return item;
    });

在玩耍时,我更改了返回以使其不可变,因为这是导致错误的原因。

这是片段,唯一的问题是这也会返回配方中数量的变化,我该如何避免

    let r = [...state.basicRecipe];

    let Array2 = [...state.recipeBasicRecipes];

    r = r.map(item => {
      let element = Array2.find(e => e._id === item._id);
      if (element) {
        item.details = item.details.map(e => {
          let detail = element.details.find(d => d._id === e._id);
          if (detail) {
            return {
              ...e,
              rate: detail.rate
            };
          }
          return e;
        });
      }
      return item;
    });

    console.log(r);

标签: javascriptarraysreactjs

解决方案


好吧,在为你做了一些研究之后,我意识到你返回的数据中的一些属性是不可写的。

例如错误:

无法分配给对象“#”的只读属性“速率”

发生是因为rateore中的itemmap不可变。为了使其工作,您必须创建该数据的副本,而不是在此处将其引用存储在您的变量中:

let r = state.basicRecipe;

let Array2 = state.recipeBasicRecipes;

r并且Array2只是对您的状态属性的引用。


您可能想要制作该数据的新副本。像这样:

let r = [...state.basicRecipe];

let Array2 = [...state.recipeBasicRecipes];

然后运行您的代码并修改您想要更改的属性。


这是您的场景的最小复制,我没有收到任何错误。请检查并建议?

class Something extends React.Component{

  state = {
     basicRecipes : [
      {
        id: 1,
        name: "IceCream",
        details: [{ id: "12", name: "milk", quantity: "50", rate: "100" },
        { id: "13", name: "cream", quantity: "50", rate: "300" }]
      },
      {
          id: 2,
          name: "Coffee",
          details: [{ id: "14", name: "Coffee bean", quantity: "60", rate: "200" },
          { id: "15", name: "water", quantity: "60", rate: "300" }]

      },
      {
          id: 3,
          name: "Tea",
          details: [{ id: "16", name: "Tea leaf", quantity: "50", rate: "700"      
          }]
    }],
    recipeBasicRecipe : [
      {
          id: 1,
          name: "IceCream",
          details: [{ id: "12", name: "milk", quantity: "50", rate: "500" },
          { id: "13", name: "cream", quantity: "50", rate: "700" }]
      },
      {
          id: 2,
          name: "Coffee",
          details: [{ id: "14", name: "Coffee bean", quantity: "60", rate: "800" },
          { id: "15", name: "water", quantity: "60", rate: "8000" }]
      }
    ]
  };

  constructor(props)
  {
    super(props);
    this.performSomeAction = this.performSomeAction.bind(this);
  }
  
  performSomeAction()
  {
    let r = [...this.state.basicRecipes];
    let Array2 = [...this.state.recipeBasicRecipe];

    return r.map(item => {
      let element = Array2.find(e => e.id === item.id);
      let tempItem = {...item}; // Make a mutable copy of Item
      if (element) {
        tempItem.details = item.details.map(e => {
          let detail = element.details.find(d => d.id === e.id);
          let tempE = {...e}; // Make a mutable copy of e
          
          if (detail) {
            tempE.rate = detail.rate;
          }
          return tempE;
        });
      }
      return tempItem;
    });
  }
  
  render()
  {
    console.log(this.performSomeAction());
    
    return(
      <h1>Code Runs</h1>
    );
  }
}

ReactDOM.render(<Something />, 
document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>


推荐阅读