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

React拆分Bootstrap Modal组件后出现TypeError: Cannot read properties of undefined (reading 'name')错误求助

解决React Bootstrap Modal拆分后出现的TypeError: Cannot read properties of undefined (reading 'name')问题

咱们来一步步拆解你遇到的问题,然后给出修复方案:

错误原因分析

  1. 重复渲染Modal组件:你在表格的每一行都渲染了一个DetailModal,这意味着页面上同时存在10个Modal实例,它们共享同一个show状态。当组件初始化时,selectedItem是空对象{},所有Modal都会尝试访问selectedItem.name,自然会触发"读取undefined的name属性"错误。
  2. props传递错误:DetailModal里试图使用list这个props,但你在父组件调用它时根本没传递这个参数,导致点击按钮时handleShow(e, list)里的list是undefined,最终selectedItem被设置为undefined,进一步加剧了错误。
  3. 初始状态无防御性处理:selectedItem初始值是空对象,当Modal尝试渲染标题时,直接访问selectedItem.name没有做任何空值判断。

修复后的代码

1. 修改ModalPractice.js

把Modal组件移到表格外面(只渲染一次),表格行里只保留触发按钮,直接调用handleShow传递当前条目:

import React, { useState } from 'react';
import { Table, Button } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import { DetailModal } from './DetailModal';

const ModalPractice = () => {
  const [show, setShow] = useState(false);
  const [selectedItem, setSelectedItem] = useState(null); // 改为null,更直观表示无选中项

  const handleClose = () => {
    setShow(false);
    setSelectedItem(null);
  };

  const handleShow = (item) => {
    setSelectedItem(item);
    setShow(true);
  };

  const food = [
    { id: 1, name: 'rice', category: 'grain', image: 'images/rice.jpg' },
    { id: 2, name: 'beans', category: 'grain and protein', image: 'images/beans.jpg' },
    { id: 3, name: 'amala', category: 'swallow', image: 'images/amala.jpg' },
    { id: 4, name: 'Oat', category: 'cereals', image: 'images/oat.jpg' },
    { id: 5, name: 'coke', category: 'soft drink', image: 'images/coke.jpg' },
    { id: 6, name: 'banana', category: 'fruit', image: 'images/banana.jpg' },
    { id: 7, name: 'okra', category: 'vegetable', image: 'images/okra.jpg' },
    { id: 8, name: 'yam', category: 'tuber', image: 'images/yam.jpg' },
    { id: 9, name: 'palm oil', category: 'fat', image: 'images/palmoil.jpg' },
    { id: 10, name: 'orange', category: 'fruit', image: 'images/orange.jpg' },
  ];

  return (
    <div>
      {/* 只渲染一个Modal,放在表格外面 */}
      <DetailModal 
        show={show} 
        handleClose={handleClose} 
        selectedItem={selectedItem} 
      />

      <Table striped bordered hover>
        <thead>
          <tr>
            <th>#</th>
            <th>Food Name</th>
            <th>Food Category</th>
            <th>Image</th>
            <th>Action</th> {/* 新增Action列 */}
          </tr>
        </thead>
        <tbody>
          {food.map((item) => (
            <tr className='align-middle' key={item.id}>
              <td>{item.id}</td>
              <td>{item.name}</td>
              <td>{item.category}</td>
              <td>
                <img alt={item.name} src={item.image} width='100' height='100' />
              </td>
              <td>
                {/* 直接在表格行里放按钮,调用handleShow传递当前item */}
                <Button variant='primary' onClick={() => handleShow(item)}>
                  Detail
                </Button>
              </td>
            </tr>
          ))}
        </tbody>
      </Table>
    </div>
  );
};

export default ModalPractice;

2. 修改DetailModal.js

简化组件职责,只负责渲染Modal内容,添加空值判断避免报错:

import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Button, Modal } from 'react-bootstrap';

export const DetailModal = (props) => {
  const { selectedItem, show, handleClose } = props;

  // 如果没有选中项,直接返回null,避免渲染空Modal
  if (!selectedItem) return null;

  return (
    <Modal show={show} onHide={handleClose}>
      <Modal.Header closeButton>
        <Modal.Title>{selectedItem.name}</Modal.Title>
      </Modal.Header>
      <Modal.Body>{selectedItem.category}</Modal.Body>
      <Modal.Footer>
        <Button variant='secondary' onClick={handleClose}>
          Close
        </Button>
        <Button variant='primary' onClick={handleClose}>
          Save Changes
        </Button>
      </Modal.Footer>
    </Modal>
  );
};

关键优化点

  • 单一Modal实例:只渲染一个Modal组件,避免重复渲染带来的性能问题和状态冲突。
  • 空值防御:在DetailModal里判断selectedItem是否存在,不存在时不渲染Modal内容,或者也可以使用可选链操作符selectedItem?.name替代直接访问。
  • 清晰的职责划分:父组件负责管理列表和选中状态,子组件只负责渲染Modal内容,逻辑更清晰易维护。

内容的提问来源于stack exchange,提问作者Abubakar Oluyinka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:12:43