英文:
React state resets when used with a composite object
问题
在React中,您遇到的问题似乎与状态管理有关。当您使用setBook
更新book
状态时,它不会保留旧状态的引用,而是创建一个新的状态对象。因此,在setContent
中使用setBook({ ...book, content })
时,它实际上是创建一个新的book
对象,其中只有content
字段发生更改,而title
字段仍然保持不变。
解决这个问题的一种方法是在setContent
中确保您在新状态对象中保留旧的title
值。这样,它不会被重置为空字符串。以下是修改后的setContent
函数:
function setContent(content: string) {
setBook({ ...book, content, title: book.title })
}
这样做可以确保在更新content
字段时不会丢失title
字段的值。
另一种方法是,您可以将初始状态设置为null
,然后在渲染BookComponent
时检查book
是否为null
,如果是,就返回一个空字符串作为默认值。这种方法允许book
在初始化时为null
,然后在加载后更新为实际的Book
对象。
希望这有助于解决您的问题。
英文:
I'm new to React. Here is the scenario:
- I have a class called Book. A book has a title and content, both strings.
- I'm trying to separate the concerns within the book page into a BookComponent (view) and Book hook (state) and a Book class (dealing with the backend API), similar to what's described here: https://martinfowler.com/articles/modularizing-react-apps.html
Here is a sample code:
export const useBook = () => {
const [book, setBook] = React.useState<Book>(new Book('', ''))
function load(id: string) {
Book.fetch(id).then((book) => { setBook(book) })
}
function title() : string {
return book.title
}
function content() : string {
return book.content
}
function setTitle(title: string) {
setBook({ ...book, title })
}
function setContent(content: string) {
setBook({ ...book, content })
}
return {
title,
setTitle,
content,
setContent
}
}
In the BookComponent (view) I have this:
<div>{book.title()}</div>
<input type="text" value={book.content()} onChange={(e) => book.setContent(e.target.value) }} />
(Omitted useEffect
code to load the book)
The page shows the title and the content correctly. However, as soon as I type anything in the textbox, the title goes back to ""
which is the initial value of the state.
I thought using setBook({...book, content})
within the hook is going to copy the existing book state and only modify content
, but it seems the code enters setContent
with a brand new book
when I inspect ...book
Changing the state to the following fixes the problem:
const [book, setBook] = React.useState<Book | null>(null)
// ...
function title() : string {
if (!book) return { '' }
return book.title
}
// same for content
But I don't understand why the state would start from a null
value (default) every time and the lifecycle of it.
答案1
得分: 1
将新状态设置为以下方式(带有回调函数),在setContent
(以及在setTitle
中同样如此)中,可以访问先前的状态,并且它应该与您的预期完全一致。使用展开运算符复制prevState
到一个新状态并覆盖content
:
setBook(prevState => ({ ...prevState, content }))
英文:
Set your new state like this (with a callback fn) inside your setContent
(and similarly in setTitle
) with an access to previous state and it should work exactly as you expected. Copy prevState with spread operateor into a new state and override content:
setBook(prevState => ({ ...prevState, content }))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论