我在React中有一个状态对象,看起来像这样(book/chapter/section/item):
const book = {
id: "123",
name: "book1",
chapters: [
{
id: "123",
name: "chapter1",
sections: [
{
id: "4r4",
name: "section1",
items: [
{
id: "443",
name: "some item"
}
]
}
]
},
{
id: "222",
name: "chapter2",
sections: []
}
]
}
我有添加或插入正在工作的新章对象的代码。我正在使用:
// for creating a new chapter:
setSelectedBook(old => {
return {
...old,
chapters: [
...old.chapters,
newChapter // insert new object
]
}
})
对于章节更新,这是有效的:
setSelectedBook(old => {
return {
...old,
chapters: [
...old.chapters.map(ch => {
return ch.id === selectedChapterId
? {...ch, name: selectedChapter.name}
: ch
})
]
}
})
但是对于我的更新/创建的部分,我有麻烦使用相同的方法。我得到语法错误试图访问部分从书。章节。例如,使用我需要的add:
// for creating a new section:
setSelectedBook(old => {
return {
...old,
chapters: [
...old.chapters,
...old.chapters.sections?
newSection // how to copy chapters and the sections and insert a new one?
]
}
})
我知道React应该返回所有以前的状态,除了你正在改变的。减速器真的会产生影响吗?
我应该注意,我有4个简单的列表在我的ui。一个书籍/章节/章节/项目的列表,在任何给定的操作中,我一次只添加/更新一个特定的关卡/对象,并在每次保存时将该对象发送给后端api。这里是books for list 1和selectedBook。并选择了ecectedchapter。和selectedSection。清单4.
但是我需要在保存完成时显示新的状态。我想我可以用一个bookState对象和一个selectedThing状态来实现这一点。
希望这是有意义的。我以前从没这么做过。谢谢你的指导。
用于添加新的Section
setSelectedBook( book =>{
let selectedChapter = book.chapters.find(ch => ch.id === selectedChapterId )
selectedChapter.sections=[...selectedChapter.sections, newSection ]
return {...book}
})
用于更新section名
setSelectedBook(book=>{
let selectedChapter = book.chapters.find(ch => ch.id === selectedChapterId )
let selectedSection = selectedChapter.sections.find(sec => sec.id === selectedSectionId )
selectedSection.name = newName
return {...book}
})
用于更新项目名称
setSelectedBook(book =>{
let selectedChapter = book.chapters.find(ch => ch.id === selectedChapterId )
let selectedSection = selectedChapter.sections.find(sec => sec.id === selectedSectionId )
let selectedItem = selectedSection.items.find(itm => itm.id === selectedItemId)
selectedItem.name = newItemName
return {...book}
})
我希望你能看到这个模式。
我认为这个地图应该适用于这个用例,就像你的例子一样。
setSelectedBook(old => {
return {
...old,
chapters: [
...old.chapters.map(ch => {
return { ...ch, sections: [...ch.sections, newSection] }
})
]
}
})
在你的最后一个代码块中,你试图将章节,章节和新章节放在同一级别的同一数组中,而不是彼此内部。
在React中更新深层嵌套状态对象总是很困难。在不了解实现的所有细节的情况下,很难说如何进行优化,但您应该认真考虑以更平坦的方式存储该状态的不同方法。有时这是不可能的,在这种情况下,有像Immer这样的库可以帮助您查看。
使用您在问题中提供的状态对象,也许您可以将所有这些数组变为具有id为key的对象:
const book = {
id: "123",
name: "book1",
chapters: {
"123": {
id: "123",
name: "chapter1",
sections: {
"4r4": {
id: "4r4",
name: "section1",
items: {
"443": {
id: "443",
name: "some item"
}
}
}
}
},
"222": {
id: "222",
name: "chapter2",
sections: {},
}
]
}
这样,在设置状态时就不再需要使用map
或find
了。
// for creating a new chapter:
setSelectedBook(old => {
return {
...old,
chapters: {
...old.chapters,
[newChapter.id]: newChapter
}
}
})
// for updating a chapter:
setSelectedBook(old => {
return {
...old,
chapters: {
...old.chapters,
[selectedChapter.id]: selectedChapter,
}
}
})
// for updating a section:
setSelectedBook(old => {
return {
...old,
chapters: {
...old.chapters,
[selectedChapter.id]: {
...selectedChapter,
sections: {
[selectedSectionId]: selectedSection
}
},
}
}
})
请让我知道如果我误解了你的问题。