React点击map渲染元素切换样式,报setActive不是函数如何解决
问题解决思路
1. 先修复setActive is not a function报错
useState的返回值是数组类型,你错误使用了对象解构语法,导致无法正确拿到状态更新方法,修改如下:
// 错误写法 const { isActive, setActive} = useState(false) // 正确写法 用数组解构 const [isActive, setActive] = useState(false)
2. 修复点击仅当前元素切换激活类的问题
你当前的isActive是全局布尔值,所有循环渲染的元素共用同一个状态判断,自然会出现点击一个所有元素都切换类的问题。
这里你已经通过dispatch把选中的元素标识存入了AppContext,完全可以直接复用context里的item值做激活判断,不需要额外声明本地状态,最终完整修正代码如下:
const ListItems = () => { const { item: activeItemValue, dispatch } = useContext(AppContext); const handler = (item) => { dispatch({ type: 'SET_ITEM', payload: item.value, }); }; return ( <div className="container"> <h2 className="smallheader">Please choose one</h2> <div className="flex flex-center"> {ITEMS.map((item) => <div className={activeItemValue === item.value ? 'active-color' : 'card'} data-index={item.value} key={item.id} onClick={() => handler(item)} > <span className="card-header">{item.name}</span> <span className="card-description">{item.description}</span> </div> )} </div> </div> ) }; export default ListItems;
实现逻辑说明
- 用
context中存储的选中项value作为激活判断的依据,点击元素时把当前元素的value存入context - 循环渲染时判断当前元素的
value是否和context中存储的选中值一致,一致就加激活类,否则用默认类 - 也避免了额外声明本地状态的冗余,逻辑更统一
如果你不需要把选中值存在全局context,也可以用本地状态实现:
const ListItems = () => { // 存储当前激活元素的value,初始值为null const [activeValue, setActiveValue] = useState(null) const handler = (item) => { // 如果需要点击同一个元素取消激活,可以加判断:setActiveValue(activeValue === item.value ? null : item.value) setActiveValue(item.value) }; return ( <div className="container"> <h2 className="smallheader">Please choose one</h2> <div className="flex flex-center"> {ITEMS.map((item) => <div className={activeValue === item.value ? 'active-color' : 'card'} key={item.id} onClick={() => handler(item)} > <span className="card-header">{item.name}</span> <span className="card-description">{item.description}</span> </div> )} </div> </div> ) };
内容的提问来源于stack exchange,提问作者Ksandra
相关产品推荐
相关产品推荐

