首页 > 解决方案 > React hooks:如何使用 useState() 更新嵌套对象的状态?

问题描述

我有这个表格,里面有我从后端得到的问题和答案,如下所示:

{
  "id": 0,
  "seq": 0,
  "ccid": "string",
  "topic": "string",
  "riskOutcome": "string",
  "condition": "string",
  "comment": "string",
  "visible": true,
  "created": "2021-10-14T14:12:48.911Z",
  "updated": "2021-10-14T14:12:48.911Z",
  "createdById": 0,
  "updatedById": 0,
  "parentContentTypeId": 0,
  "questionTypeId": 0,
  "subContentTypes": [
    {
      "id": 0,
      "seq": 0,
      "ccid": "string",
      "type": "string",
      "topic": "string",
      "riskOutcome": "string",
      "condition": "string",
      "comment": "string",
      "visible": true,
      "created": "2021-10-14T14:12:48.911Z",
      "updated": "2021-10-14T14:12:48.911Z",
      "createdById": 0,
      "updatedById": 0,
      "parentContentTypeId": 0,
      "subContentTypes": [
        null
      ],
      "textI18Ns": [
        {
          "id": 0,
          "text": "string",
          "languageCode": "string",
          "type": "string",
          "contentTypeId": 0
        }
      ]
    }
  ],
  "textI18Ns": [
    {
      "id": 0,
      "text": "string",
      "languageCode": "string",
      "type": "string",
      "contentTypeId": 0
    }
  ]
}

subContentTypes 数组中是答案,而 textI18Ns 中是显示答案的文本。

我用这个将问题的答案分开

const [answerData, setAnswerData] = useState();

function getDatafromBackend = () =>{
            dispatch(getOneQuestion(data))
            .unwrap()
            .then((originalPromiseResult) => {
                var options = {};
                Object.entries(originalPromiseResult.subContentTypes).map(([key, value]) =>   {
                    options[key] = value;
                })  
                console.log("answertdata ", options)

                setAnswerData(options);
               }
}

现在我想做的是,从答案状态编辑文本。我的 JSX 看起来像这样:

let datalist = Object.entries(answerData).map(([key, value]) => {
return (<Paper elevation={3} style={{ margin: 10 }} key={"answerlist"+key}>
                    <Typography style={{ margin: 10}}>{"Daten zur Antwort: "}{answerData[key].ccid} </Typography>
                    {
                        Object.entries(answerData[key].textI18Ns).map(([index,value]) =>{
                            return (
                                <Paper elevation={3} style={{ margin: 10}} key={"questiontext"+index}>
                                    <TextField label={"Text ID"} disabled className="QuestionDataField" value={answerData[key].textI18Ns[index].id} fullWidth></TextField><br />
                                    <TextField label={"Content Typ ID"} disabled className="QuestionDataField" value={answerData[key].textI18Ns[index].contentTypeId} fullWidth></TextField><br />
                                    <TextField label={"Typ"} className="QuestionDataField" value={answerData[key].textI18Ns[index].type} fullWidth onChange={(event) => { updateAnswerTexts(event, 'type', key, index) }}></TextField><br />
                                    <TextField label={"Text"} multiline className="QuestionDataField" value={answerData[key].textI18Ns[index].text} fullWidth onChange={(event) => { updateAnswerTexts(event, 'text',key, index) }}></TextField><br />
                                    <TextField label={"Sprache"} className="QuestionDataField" value={answerData[key].textI18Ns[index].languageCode} fullWidth onChange={(event) => { updateAnswerTexts(event, 'languageCode', key, index) }}></TextField><br />
                                    <Divider/>
                                </Paper>
                            )
                        })
                    )}
setTableBody(datalist)

这是问题所在。我尝试了什么:制作一个副本,更改它并设置更改的对象

    const updateAnswerTexts = (event,prop,key, index) =>{
        let oldstate = answerData[index].textI18Ns[key];
        let updatedstate = {...oldstate, [prop]: event.target.value};
        let newstatetexts =  Object.assign({}, answerData);



        //Here is the Problem. Console says "Uncaught TypeError: 0 is read-only setSTate"
        newstatetexts[index].textI18Ns[key] = updatedstate;
        setAnswerData(newstatetexts)

        setAnswerData((prevState) => {
            prevState[index].textI18Ns[key] = updatedstate;
            return({
                ...prevState
            })
        })
    }
}

另一个尝试:控制台说,[prop] 是只读的

    const updateAnswerTexts = (event,prop,key, index) =>{
       
         setAnswerData((prevState) => {
             prevState[index].textI18Ns[key][prop] = event.target.value;
             return({
                 ...prevState
             })
         })
    }

另一个尝试:控制台说,[prop] 也是只读的

    const updateAnswerTexts = (event,prop,key, index) =>{
        let oldstate = answerData[index].textI18Ns[key];
        let updatedstate = {...oldstate, [prop]: event.target.value};
        setAnswerData((prevState) => {
            prevState[index].textI18Ns[key] = updatedstate;
            return({
                ...prevState
            })
        })
    }

标签: reactjsreact-hookssetstate

解决方案


这是为我做的

    const updateAnswerTexts = (event,prop,key, index) =>{

        let allanswers = {...answerTextsData};

        let oneanwerobj = {...allanswers[key]};
        
        let answertexts = {...oneanwerobj[index]}
        
        answertexts[prop] = event.target.value;
        oneanwerobj[index] = answertexts;
        allanswers[key] = oneanwerobj
        
        
        setAnswerTextsData(allanswers);
    }

推荐阅读