You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中useEffect传参及模态框数据加载报错问题排查

问题

我是React新手,对useEffect概念理解有困惑。在Portfolio组件中,通过cardData数组自动生成卡片,每张卡片映射生成带对应数据id的按钮。需求是鼠标悬停时获取按钮id,匹配cardData中的对应对象,点击按钮时打开模态框展示该对象内容。但将mouseId传入handleData时返回undefined,出现Cannot read properties of undefined (reading 'title')报错,硬编码数值则能正常运行。怀疑是useEffect无法通过props传递数据,或是数据在点击后才设置导致模态框无法获取内容。

相关核心代码:

function Portfolio(){
    const [modalOpen, setModalOpen] = useState(false);
    const close = () => setModalOpen(false);
    const open = () =>  setModalOpen(true) ;
    
    const [letterClass, setLetterClass] = useState("text-animate");
    const [ mouseId, setMouseId ] = useState(1);
    const [modalData, setModalData] = useState([]);
    
    useEffect(() => {
        setTimeout(() => {
          return setLetterClass('text-animate-hover')
        }, 3000)
      }, [])

      function handleMouseOver(event) {
        setMouseId(event.target.id)
      }

      function handleData(data){
        setModalData(cardData.find(obj => obj.id === data))
      }

    // 调用handleData的useEffect
    useEffect(() => {
        handleData(mouseId)
    }, [mouseId])

    // 点击事件
    function handleClick() {
        if (!modalOpen) {
            open();
        } else if (modalOpen) {
            close();
        }
    }

    return (<>
    <div className="port-content">
        <div className="container portfolio-page">
            <div className="port-text-zone">
                <h1>
                <AnimatedLetters idx={15} letterClass={letterClass} strArray={["M","y"," ","p","o","r","t","f","o","l","i","o","."]}/>
                </h1>
                <p>Since I'm such a versatile junior, I've worked on many different types of projects. My projects include design, front-end development and back-end development.</p>
            </div> 
        </div>
        <GeneratedCards id={handleClick} mouse={handleMouseOver}/>
    </div>
    {modalOpen && <> 
        <Modal modalOpen={modalOpen} handleClose={close} />
        <ModalContent
             title={modalData.title}
             content={modalData.description}
             desc1={modalData.modalDescription1}
             desc2={modalData.modalDescription2}
             desc3={modalData.modalDescription3}
             projectLink={modalData.title} 
        />
    </>}
        <Loader type="ball-grid-beat" />
    </>)
}

export default Portfolio;

解决方案

1. 核心问题:类型不匹配

event.target.id返回的是字符串类型,而cardData中的id是数值类型,使用全等===匹配时找不到对应对象,返回undefined,导致modalData为undefined,访问modalData.title时触发报错。

2. 优化修改步骤

步骤1:修复类型匹配问题

在handleMouseOver中将字符串id转为数值:

function handleMouseOver(event) {
  // 将字符串id转为数值类型
  setMouseId(Number(event.target.id))
}

或者在handleData中转换匹配的类型:

function handleData(data){
  setModalData(cardData.find(obj => obj.id === Number(data)))
}

步骤2:移除冗余的useEffect监听

没必要通过useEffect监听mouseId来更新modalData——悬停时提前加载数据是无意义的,应该在点击按钮时直接获取对应数据,减少不必要的状态更新:

  • 修改handleClick,让它接收卡片id参数,直接获取数据并打开模态框:
function handleClick(cardId) {
  // 转换类型并匹配数据
  const selectedData = cardData.find(obj => obj.id === Number(cardId));
  setModalData(selectedData);
  setModalOpen(true);
}
  • 在GeneratedCards组件中,给按钮的点击事件传递对应卡片的id(假设卡片数据是card):
// GeneratedCards内部的按钮元素
<button 
  id={card.id} 
  onClick={() => props.id(card.id)} 
  onMouseOver={() => props.mouse(card.id)}
>
  {/* 按钮内容 */}
</button>

同时修改handleMouseOver直接接收id:

function handleMouseOver(cardId) {
  setMouseId(Number(cardId))
}

步骤3:处理初始状态避免渲染报错

将modalData的初始状态设为null,并在渲染ModalContent时添加判断,避免初始或数据未加载时访问属性报错:

// 初始化状态
const [modalData, setModalData] = useState(null);

// 渲染部分
{modalOpen && modalData && <> 
  <Modal modalOpen={modalOpen} handleClose={close} />
  <ModalContent
       title={modalData.title}
       content={modalData.description}
       desc1={modalData.modalDescription1}
       desc2={modalData.modalDescription2}
       desc3={modalData.modalDescription3}
       projectLink={modalData.title} 
  />
</>}

或者使用可选链操作符简化:

<ModalContent
     title={modalData?.title}
     content={modalData?.description}
     desc1={modalData?.modalDescription1}
     desc2={modalData?.modalDescription2}
     desc3={modalData?.modalDescription3}
     projectLink={modalData?.title} 
/>

内容的提问来源于stack exchange,提问作者Henry Ford

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:57:37