I have this form with questions and answers i get from the backend like this:
{
"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
}
]
}
in the subContentTypes Array are the answers and within textI18Ns is the text for the answers that is shown.
I seperate the answers from the question with this
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);
}
}
Now what I want to do is, to edit a Text from the Answer State. My JSX looks like this:
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)
Here is the Problem. What i tried: Make a copy, change it and set the changed object
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
})
})
}
}
Another try: Here the Console says, [prop] is read only
const updateAnswerTexts = (event,prop,key, index) =>{
setAnswerData((prevState) => {
prevState[index].textI18Ns[key][prop] = event.target.value;
return({
...prevState
})
})
}
Another try: Here the Console says, [prop] is read only too
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
})
})
}
To achieve what you want you'd have to spread every single level of the object, eg.
{
name: 'john'
job: {
name: "chief",
address: {
city: "London",
street: "Baker street"
}
}
}
To modify street in useState:
setState(prevState => ({
...prevState,
job: {
...prevState.job,
address: {
...prevState.job.address,
street: "New street"
}
}
}))
Sadly this is how it is, you should rather refactor youre state, use class component instead of functional, use some global store, or maybe some library for forms :)
This did it for me
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);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.