【问题标题】:React hooks: How do I update state on a nested object with array with useState()?React hooks:如何使用 useState() 更新嵌套对象的状态?
【发布时间】:2021-10-14 14:37:40
【问题描述】:

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

{
  "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
            })
        })
    }

【问题讨论】:

  • 这不是一个好方法,但您可以通过切换另一个布尔状态或其他东西来强制更新。

标签: reactjs react-hooks setstate


【解决方案1】:

要实现您想要的,您必须分散对象的每个级别,例如。

{
  name: 'john'
  job: {
    name: "chief",
    address: {
      city: "London",
      street: "Baker street"
    }
  }
}

修改useState中的街道:

setState(prevState => ({
   ...prevState,
   job: {
      ...prevState.job,
      address: {
         ...prevState.job.address,
         street: "New street"
      }
   }
}))

遗憾的是,事情就是这样,你应该重构你的状态,使用类组件而不是函数,使用一些全局存储,或者可能是一些表单库:)

【讨论】:

    【解决方案2】:

    这是为我做的

        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);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-12
      • 1970-01-01
      • 1970-01-01
      • 2020-01-07
      • 1970-01-01
      • 2023-01-31
      相关资源
      最近更新 更多