React中removeBook正常,addToShelf报setState不是函数错误
问题分析与解决方案
问题根源
你的addToShelf函数报错的核心原因是:BookDetailShelf组件期望接收三个setState函数,但父组件MyLibrary中的CardGridShelf只传递了当前书架对应的那一个。
看MyLibrary的代码:
- 渲染「To Read」标签页的
CardGridShelf时,只传了setToReadList,没有传setReadingNowList和setHaveReadList; - 同理,「Reading Now」和「Have Read」的
CardGridShelf也只传递了各自对应的set函数。
这就导致BookDetailShelf中未被传递的那两个set函数是undefined:
- 如果你在「To Read」的弹窗里执行添加到「Have Read」的操作,
setHaveReadList是undefined,调用时就会抛出TypeError; - 而
removeBook能正常工作,是因为删除操作针对的是当前书架,接口返回的shelfResponse刚好匹配当前书架的id,调用的是已传递的set函数,所以不会触发错误。
修复方案
在MyLibrary的每个CardGridShelf组件中,补充传递所有三个setState函数:
// 「To Read」标签页的CardGridShelf <CardGridShelf books={toReadList} shelfId={2} setToReadList={setToReadList} setReadingNowList={setReadingNowList} setHaveReadList={setHaveReadList} /> // 「Reading Now」标签页的CardGridShelf <CardGridShelf books={readingNowList} shelfId={3} setToReadList={setToReadList} setReadingNowList={setReadingNowList} setHaveReadList={setHaveReadList} /> // 「Have Read」标签页的CardGridShelf <CardGridShelf books={haveReadList} shelfId={4} setToReadList={setToReadList} setReadingNowList={setReadingNowList} setHaveReadList={setHaveReadList} />
这样无论你在哪个书架的弹窗里执行添加操作,对应的set函数都已存在,不会再抛出“不是函数”的错误。
额外优化建议
可以考虑将三个书架的状态合并为一个对象,用单个setState函数管理,这样能减少props传递的复杂度,比如:
const [shelves, setShelves] = useState({ toRead: [], readingNow: [], haveRead: [] });
后续更新状态时只需调用setShelves(prev => ({ ...prev, [shelfKey]: updatedList })),也避免了多个set函数传递的问题。
内容的提问来源于stack exchange,提问作者Lennie C
相关产品推荐
相关产品推荐

