React useState异常:点击卡片新增对象时cards状态更新不符合预期
问题根源
React状态更新为异步批量执行,你在调用setcurrCard后立刻读取currCard拿到的是本次渲染的旧值,并非刚设置的新组件,所以才会出现cardtitle和card内容不匹配、卡片追加异常的问题。
解决方案
直接根据传入的卡片名称生成对应组件,不要依赖异步更新的currCard来更新cards状态,同时可以用映射表简化冗余的switch判断,修改后完整代码如下:
import Head from 'next/head' import { useState } from 'react' import Developer from '../components/Developer'; import Invite from '../components/Invite'; import Parents from '../components/Parents'; import RSVP from '../components/RSVP'; import Schedule from '../components/Schedule'; import Venue from '../components/Venue'; import Welcome from '../components/Welcome'; import styles from '../styles/Home.module.css' // 组件映射表,后续新增卡片只需在此处添加配置即可 const CARD_COMPONENTS = { Welcome: <Welcome />, Invite: <Invite />, Schedule: <Schedule />, Parents: <Parents />, Venue: <Venue />, RSVP: <RSVP />, Developer: <Developer /> } function Home() { const [cards, setCards] = useState([]); const [currCard , setcurrCard] = useState('Select a Card'); const addCard = (cardName) => { // 直接获取对应组件 const targetCard = CARD_COMPONENTS[cardName] // 更新当前选中卡片 setcurrCard(targetCard) // 判断卡片是否已经存在 const isExist = cards.some(item => item.cardtitle === cardName) if (isExist) return // 不存在就追加到cards数组 setCards(prev => [...prev, { cardtitle: cardName, card: targetCard }]) } return ( <div className="bg-black"> <Head> <title>Create Next App</title> <meta name="description" content="Generated by create next app" /> <link rel="icon" href="/favicon.ico" /> </Head> <main> <div className={styles.main}> <div className="options"> <h2 onClick={() => addCard('Welcome')}>Welcome Card</h2> <h2 onClick={() => addCard('Invite')}>Invite Card</h2> <h2 onClick={() => addCard('Schedule')}>Schedule Card</h2> <h2 onClick={() => addCard('Parents')}>Parents Card</h2> <h2 onClick={() => addCard('Venue')}>Venue Card</h2> <h2 onClick={() => addCard('RSVP')}>RSVP Card</h2> <h2 onClick={() => addCard('Developer')}>Developers Card</h2> </div> {/* 渲染当前选中卡片 */} <div> {currCard} </div> </div> {/* 渲染所有已选中的卡片 */} <div> {cards.map((card, idx) => ( <div key={idx}>{card.card}</div> ))} </div> </main> </div> ) } export default Home;
关键改动说明
- 新增组件映射表,替代冗余的switch分支,后续维护更便捷
- 不再依赖异步更新的
currCard变量组装新卡片项,直接根据传入的卡片名称获取对应组件,保证数据同步 - 优化了卡片去重逻辑,代码更简洁
- 更新
cards时使用函数式写法setCards(prev => ...),避免依赖旧状态可能出现的更新异常 - 给
map渲染的卡片添加了key属性,符合React语法规范
内容的提问来源于stack exchange,提问作者Hajra
相关产品推荐
相关产品推荐

