You need to enable JavaScript to run this app. React useState异常:点击卡片新增对象时cards状态更新不符合预期
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 05:45:02