在 React 中,当我在另一个组件中触发 Add 函数时,如何正确使用钩子来更新一个组件?
In React, how do I properly use hooks to update one component when I trigger an Add function in another component?
我正在构建一个用于查找书籍以学习 React 的应用程序。我不知道如何将 所有 本书 ("Book List") 列表中的一本书添加到单独的 "Reading List" 中。我有一个 JSON 书籍数据文件,如下所示:
[
{
"descr": "Take a voyeuristic look at life in Sheffield...",
"author": "Philip Hensher",
"title_id": "9812",
"title": "The Northern Clemency",
"cover": "https://www.whichbook.net/assets/images/big/9812.jpg",
"similar": "https://www.whichbook.net/#cmd=search&search-type=3&id=9812"
},
...
]
我在我的 BookList.js 组件中循环遍历它们以显示每本书和一个指向 "Add to Reading List" 的按钮,如下所示:
export default function BookList ({ handleAddBook }) {
return (
<div>
{BookData.map((book) => {
return (
<>
<BookDetail key={book.title_id} book={book} />
<button onClick={handleAddBook}>Add to Reading List</button>
</>
)
})}
</div>
)
}
对于每个 BookDetail,我只显示标题和 title_id。在 BookDetail.js:
export default function BookDetail({ book }) {
return (
<div>
<h1>{book.title}</h1>
<p>{book.title_id}</p>
</div>
)
}
效果很好。我看到了我所有书籍的清单。现在,在我的 ReadingList.js 中,我尝试循环浏览类似于我的 BookList 的书籍,除了功能组件有一个 booksToRead
参数:
export default function ReadingList({ booksToRead }) {
return (
<div>
<h3>My Reading List</h3>
{booksToRead.map((book) => {
return (
<>
<BookDetail key={book.title_id} book={book} />
</>
)
})}
</div>
)
}
好的,现在让我们看看 App.js 我试图解决这个问题的地方。基本上,每当常量 newBookToRead
发生变化时,我都会尝试使用 useState()
和 useEffect()
来更新我的 booksToRead
数组,这是在 handleAddBook
函数中处理的。我用虚拟数据初始化 booksToRead
,它显示在浏览器中,但从不更新。
function App() {
const [books, setBooks] = useState([])
const [booksToRead, setBooksToRead] = useState([{ title: 'initialBookToRead', title_id: '1234' }])
const [newBookToRead, setNewBookToRead] = useState([{ title: 'addMe', title_id: '000' }])
function handleAddBook() {
setNewBookToRead(newBookToRead)
}
useEffect(() => {
setBooksToRead(booksToRead => [...booksToRead, newBookToRead])
}, [newBookToRead])
return (
<main>
<BookList books={books} />
<ReadingList booksToRead={booksToRead} />
</main>
);
}
export default App;
我试过将逻辑转移到不同的组件,我试过用 createContext
创建一个 ReadingListContext 并使用 ReadingListContext.Provider value={booksToRead}
而不是 <ReadingList>
标签,我只是想不通。
此外,可能不相关,我的控制台为我提供了 BookList
和 ReadingList
的 Warning: Each child in a list should have a unique "key" prop.
,即使我将密钥设置为 book.title_id
这是一个唯一代码. ????
export default function BookList ({ books, handleAddBook }) {
return (
<div>
{books.map((book) => {
const onAddBook = () => handleAddBook(book);
return (
<>
<BookDetail key={book.title_id} book={book} />
<button onClick={onAddBook}>Add to Reading List</button>
</>
)
})}
</div>
)
}
function App() {
const [books, setBooks] = useState([])
const [booksToRead, setBooksToRead] = useState([{ title: 'initialBookToRead', title_id: '1234' }])
function handleAddBook(book) {
setBooksToRead([...booksToRead, book])
}
return (
<main>
<BookList books={books} handleAddBook={handleAddBook}/>
<ReadingList booksToRead={booksToRead} />
</main>
);
}
export default App;
请使用以上组件。您需要将书作为参数传递给 handleAddBook。无需存储 newBookToRead 和 useEffect,您可以使用提到的 handleAddBook。
我正在构建一个用于查找书籍以学习 React 的应用程序。我不知道如何将 所有 本书 ("Book List") 列表中的一本书添加到单独的 "Reading List" 中。我有一个 JSON 书籍数据文件,如下所示:
[
{
"descr": "Take a voyeuristic look at life in Sheffield...",
"author": "Philip Hensher",
"title_id": "9812",
"title": "The Northern Clemency",
"cover": "https://www.whichbook.net/assets/images/big/9812.jpg",
"similar": "https://www.whichbook.net/#cmd=search&search-type=3&id=9812"
},
...
]
我在我的 BookList.js 组件中循环遍历它们以显示每本书和一个指向 "Add to Reading List" 的按钮,如下所示:
export default function BookList ({ handleAddBook }) {
return (
<div>
{BookData.map((book) => {
return (
<>
<BookDetail key={book.title_id} book={book} />
<button onClick={handleAddBook}>Add to Reading List</button>
</>
)
})}
</div>
)
}
对于每个 BookDetail,我只显示标题和 title_id。在 BookDetail.js:
export default function BookDetail({ book }) {
return (
<div>
<h1>{book.title}</h1>
<p>{book.title_id}</p>
</div>
)
}
效果很好。我看到了我所有书籍的清单。现在,在我的 ReadingList.js 中,我尝试循环浏览类似于我的 BookList 的书籍,除了功能组件有一个 booksToRead
参数:
export default function ReadingList({ booksToRead }) {
return (
<div>
<h3>My Reading List</h3>
{booksToRead.map((book) => {
return (
<>
<BookDetail key={book.title_id} book={book} />
</>
)
})}
</div>
)
}
好的,现在让我们看看 App.js 我试图解决这个问题的地方。基本上,每当常量 newBookToRead
发生变化时,我都会尝试使用 useState()
和 useEffect()
来更新我的 booksToRead
数组,这是在 handleAddBook
函数中处理的。我用虚拟数据初始化 booksToRead
,它显示在浏览器中,但从不更新。
function App() {
const [books, setBooks] = useState([])
const [booksToRead, setBooksToRead] = useState([{ title: 'initialBookToRead', title_id: '1234' }])
const [newBookToRead, setNewBookToRead] = useState([{ title: 'addMe', title_id: '000' }])
function handleAddBook() {
setNewBookToRead(newBookToRead)
}
useEffect(() => {
setBooksToRead(booksToRead => [...booksToRead, newBookToRead])
}, [newBookToRead])
return (
<main>
<BookList books={books} />
<ReadingList booksToRead={booksToRead} />
</main>
);
}
export default App;
我试过将逻辑转移到不同的组件,我试过用 createContext
创建一个 ReadingListContext 并使用 ReadingListContext.Provider value={booksToRead}
而不是 <ReadingList>
标签,我只是想不通。
此外,可能不相关,我的控制台为我提供了 BookList
和 ReadingList
的 Warning: Each child in a list should have a unique "key" prop.
,即使我将密钥设置为 book.title_id
这是一个唯一代码. ????
export default function BookList ({ books, handleAddBook }) {
return (
<div>
{books.map((book) => {
const onAddBook = () => handleAddBook(book);
return (
<>
<BookDetail key={book.title_id} book={book} />
<button onClick={onAddBook}>Add to Reading List</button>
</>
)
})}
</div>
)
}
function App() {
const [books, setBooks] = useState([])
const [booksToRead, setBooksToRead] = useState([{ title: 'initialBookToRead', title_id: '1234' }])
function handleAddBook(book) {
setBooksToRead([...booksToRead, book])
}
return (
<main>
<BookList books={books} handleAddBook={handleAddBook}/>
<ReadingList booksToRead={booksToRead} />
</main>
);
}
export default App;
请使用以上组件。您需要将书作为参数传递给 handleAddBook。无需存储 newBookToRead 和 useEffect,您可以使用提到的 handleAddBook。