简体   繁体   English

React.js:更新嵌套对象的状态

[英]React.js : Updating State of Nested Object

Front End - Front End Upon clicking the star, I want to update the state of nested object, with the new rating value of star.前端 -前端单击星标后,我想使用星号的新评级值更新嵌套对象的状态。

I tried many things but it didnt work as states are immutable.我尝试了很多东西,但它不起作用,因为状态是不可变的。

Nested State嵌套状态

Can some upon please suggest how can I update the value in nested object有人可以建议我如何更新嵌套对象中的值

onStarClicked = (kTypName, subItemId1, newRating) => {
//console.log(subItemId.split("_"));
let evaluation = subItemId1.split("_")[0];
let subItemId = subItemId1.split("_")[1];
console.log(subItemId);
const r = { ...this.state.ratings };
let kT = r.knowledgeTypes;
let sub = '', kTN = '', kIN = '';
kT.map(knowledgeType => {
  //console.log(knowledgeType.knowledgeTypeId);
  knowledgeType.knowledgeItems.map(knowledgeItem => {
    //console.log(knowledgeItem.knowledgeItemId);
    knowledgeItem.subItems.map(knowledgeSubItem => {
      //console.log(knowledgeSubItem.subItemId);
      if (subItemId === knowledgeSubItem.subItemId) {
        kTN = knowledgeType.knowledgeTypeName;
        kIN = knowledgeItem.knowledgeItemName;
        sub = knowledgeSubItem;
        if (evaluation === "self") {
          sub.evaluation.self.rating = newRating;
        }
        else if (evaluation === "evaluator") {
          sub.evaluation.evaluator.rating = newRating;
        }

        //alert(evaluation + subItemId + ' ' + newRating);
        //return;
      }
    })
  })

});


this.setState({
  ...this.state,
  ratings: {
    ...this.state.ratings,
    knowledgeTypes: [
      ...this.state.ratings.knowledgeTypes,
      this.state.ratings.knowledgeTypes.filter(kt => kt.knowledgeTypeName !== kTN),
      {
        ...this.state.ratings.knowledgeTypes.knowledgeItems.
          filter(ki => ki.knowledgeItemName !== kIN),
        knowledgeItems: {
          ...this.state.ratings.knowledgeTypes.knowledgeItems.subItems.
            filter(si => si.subItemId !== subItemId),
          sub
        }
      }]
  }
});

} }

You basically have to create a new empty array of knowledgeTypes and use the current state to find which item of the state you need to change using Object.keys/map/filter functions.您基本上必须创建一个新的knowledgeTypes空数组,并使用当前状态来查找需要使用Object.keys/map/filter函数更改的状态项。

You'd use the current state in a variable and modify that variable only.您将在变量中使用当前状态并仅修改该变量。 You'd likely not mess with the actual state object in any way.您可能不会以任何方式弄乱实际的状态对象。

After you have done that, simply append it to the empty array.完成后,只需将其附加到空数组。 Then you can setState() the new array to the actual state property.然后您可以将新数组 setState() 设置为实际的 state 属性。

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      financialYear: "2019-20",
      quarter: "Q1",
      isCurrentQuarter: true,
      knowledgeTypes: [
        {
          knowledgeTypeName: "Technology",
          knowledgeItems: [
            {
              knowledgeItemName: "Java",
              subItems: [
                {
                  subItemId: "2",
                  subItemName: "Collections",
                  evaluation: {
                    self: {
                      ntnet: "Joe",
                      rating: 1,
                      isEditable: true
                    }
                  }
                }
              ]
            }
          ]
        }
      ]
    };
  }

  handleClick = e => {
    const { knowledgeTypes } = this.state;

    // transformation
    const itemToChange = knowledgeTypes.map(item => {
      if (item.knowledgeTypeName === "Technology") {
        return item;
      }
    });
    const currItems = itemToChange[0].knowledgeItems[0].subItems;
    const subItem = currItems.map(item => {
      if (item.subItemId === "2") {
        return item;
      }
    });
    const person = subItem[0].evaluation;
    person.self.rating = 55; //change

    const newKnowledgeTypes = [];
    knowledgeTypes.map(item => {
      if (item.knowledgeTypeName === "Technology") {
        newKnowledgeTypes.push(itemToChange);
      }
      newKnowledgeTypes.push(item);
    });

    this.setState({
      knowledgeTypes: newKnowledgeTypes
    });

    console.log(this.state);
  };

  render() {
    return (
      <div>
        MyComponent
        <button onClick={this.handleClick}>Hello</button>
      </div>
    );
  }
}


The sandbox can be found on https://codesandbox.io/s/musing-dew-8r2vk .沙箱可以在https://codesandbox.io/s/musing-dew-8r2vk上找到。

Note: It is advisable you do not use nested state objects because state objects are something more lightweight so that they do not have performance considerations.注意:建议您不要使用嵌套状态对象,因为状态对象更轻量级,因此它们没有性能方面的考虑。

import React, { Component } from 'react';
import Auxilary from '../../../hoc/Auxilary/auxilary';
import KnowledgeItems from '../KnowledgeItems/KnowledgeItems';
import Tabs from 'react-bootstrap/Tabs';
import Tab from 'react-bootstrap/Tab';
import knowledge from '../../../assests/staticdata.json';

import './QuarterLog.css';

class QuarterLog extends Component {

  constructor() {
    super();
    this.state = {
      "financialYear": "",
      "quarter": "",
      "isCurrentQuarter": "",
      "knowledgeTypes": []
    }
  }

  onStarClicked = (kTypName, kItemName, subItemIdName, newRating) => {
    let evaluation = subItemIdName.split("_")[0];
    let subItemId = subItemIdName.split("_")[1];

    const { knowledgeTypes } = this.state;

    // transformation
    let knowledgeTypeToChange = knowledgeTypes.map(kType => {
      if (kType.knowledgeTypeName === kTypName) {
        return kType;
      }
    });

    knowledgeTypeToChange = knowledgeTypeToChange.filter(function (element) {
      return element !== undefined;
    });

    console.log(knowledgeTypeToChange[0]);
    let knowledgeItemToChange = knowledgeTypeToChange[0].knowledgeItems.map(item => {
      if (item.knowledgeItemName === kItemName) {
        return item;
      }
    });

    knowledgeItemToChange = knowledgeItemToChange.filter(function (element) {
      return element !== undefined;
    });

    let knowledgeSubItem = knowledgeItemToChange[0].subItems.map(subItem => {
      if (subItem.subItemId === subItemId) {
        return subItem;
      }
    });

    knowledgeSubItem = knowledgeSubItem.filter(function (element) {
      return element !== undefined;
    });

    console.log(knowledgeSubItem);

    let personEvaluations = knowledgeSubItem[0].evaluation;

    if (evaluation === "self") {
      personEvaluations.self.rating = newRating.toString(); //change
    }
    else if (evaluation === "evaluator") {
      personEvaluations.evaluator.rating = newRating.toString(); //change
    }

    const newKnowledgeTypes = [];
    knowledgeTypes.map(item => {
      if (item.knowledgeTypeName === kTypName) {
        newKnowledgeTypes.push(knowledgeTypeToChange[0]);
      }
      else
        newKnowledgeTypes.push(item);
    });

    this.setState({
      knowledgeTypes: newKnowledgeTypes
    });

    console.log(this.state);

  }

  componentDidMount() {
    // TODO: remove staticdata.js and call REST API and set the response in state
    this.setState({
      ...this.state,
      "financialYear": knowledge.financialYear,
      "quarter": knowledge.quarter,
      "isCurrentQuarter": knowledge.isCurrentQuarter,
      "knowledgeTypes": knowledge.knowledgeTypes
    })

  }

  onSubmitRatings = () => {
    console.log(this.state);
  }

  render() {
    let data = knowledge; //remove this code, once REST API is implemented

    const posts = this.state.knowledgeTypes.map(knowledgeType => {
      return (
        <Tab key={knowledgeType.knowledgeTypeName} eventKey={knowledgeType.knowledgeTypeName}
          title={knowledgeType.knowledgeTypeName}>
          <KnowledgeItems
            kTypeName={knowledgeType.knowledgeTypeName}
            kItems={knowledgeType.knowledgeItems}
            ratings={this.state.ratings}
            onstarclicked={this.onStarClicked}
          />
        </Tab>)
    });

    return (
      <Auxilary>
        <div className="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
          <div><h1>Financial Year : {data.financialYear}</h1></div>
          <div><h2>Quarter : {data.quarter}</h2></div>
        </div>
        <div>
          <Tabs defaultActiveKey="Domain" id="uncontrolled-tab-example">
            {posts}
          </Tabs>
        </div>
        <button onClick={this.onSubmitRatings}> Submit </button>
      </Auxilary>
    );
  }
}

export default QuarterLog;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM