React开发圣诞礼物清单报setAvailability is not a function错误咨询
问题原因
你报错的直接原因是GiftItem组件中useState用法错误:
- React的
useState返回值是长度为2的数组,第一个元素是状态变量,第二个才是状态修改函数,你现在直接把整个返回值赋值给setAvailability,拿到的是数组而不是函数,自然调用的时候会报not a function的错误。 - 另外你这里
useState的初始值写法也有误,你把props传入的available包裹成了对象{available},和实际需要的布尔值类型不符。 - 还有一个隐藏问题:你当前的
giftList是静态数据,没有把礼物的可用状态提升到上层组件维护的话,就算组件内状态改了,重新渲染的时候还是会用giftList里的初始值,状态不会持久。
解决方案
修复直接报错
先修改GiftItem组件的useState写法,即可解决类型报错:
// GiftItem.js 中原来的错误写法 // const setAvailability = useState({available}) // 替换为正确写法 const [isAvailable, setIsAvailable] = useState(available)
同时修改传给Book组件的参数:
<Book available={isAvailable} setAvailability={setIsAvailable} />
改完之后点击按钮就可以正常切换礼物的可用状态。
可选优化:状态提升实现状态持久化
如果需要切换分类、刷新页面后礼物的预订状态依然保留,需要把状态提升到上层的ShoppingList组件维护:
- 在ShoppingList中把giftList转为响应式状态,新增修改状态的方法:
function ShoppingList() { const [activeCategory, setActiveCategory] = useState('') // 新增giftData状态,用静态giftList作为初始值 const [giftData, setGiftData] = useState(giftList) // 新增修改礼物可用状态的方法 const updateGiftAvail = (giftName, status) => { setGiftData(prev => prev.map(item => { if(item.name === giftName) return {...item, available: status} return item })) } // 原有分类逻辑不变 const categories = giftData.reduce( (acc, gift) => acc.includes(gift.category) ? acc : acc.concat(gift.category), [] ) return ( <div className='shopping-list'> <Categories categories={categories} setActiveCategory={setActiveCategory} activeCategory={activeCategory} /> <ul className='gift-list'> {/* 遍历giftData而不是原来的静态giftList */} {giftData.map(({image, name, available, lien1, lien2, lien3, price, category}) => ( !activeCategory || activeCategory === category ? ( <GiftItem image={image} name={name} available={available} lien1={lien1} lien2={lien2} lien3={lien3} price={price} key={name} {/* 把修改方法传给GiftItem */} updateAvail={updateGiftAvail} /> ) : null ))} </ul> </div> ) }
- GiftItem组件不需要再维护内部状态,直接调用父组件传入的方法即可:
// GiftItem.js 中删除原有的useState代码 function GiftItem({image, name, available, lien1, lien2, lien3, price, category, updateAvail}) { return ( // 原有结构不变 <Book available={available} setAvailability={(val) => updateAvail(name, val)} /> // 原有结构不变 ) }
内容的提问来源于stack exchange,提问作者Cams03
相关产品推荐
相关产品推荐

