英文:
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 }))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论