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

使用react-bootstrap/Modal组件无法获取正确值的问题

问题:React-Bootstrap Modal点击后总是显示最后一条数据

开发React应用时,使用Button、Table等组件正常,但使用react-bootstrap/Modal时出现异常:点击任意按钮,Modal始终显示JSON列表中最后一个对象的内容。

服务器端JSON数据

let jsonlist = [
    {
        Title: "first title",
        Listofitems: ["Item 01", "Item 02", "Item 03"]
    },
    {
        Title: "second title",
        Listofitems: ["Item 04", "Item 05", "Item 06"]
    }
]

客户端处理代码

import { React, useEffect, useState, useRef } from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';

const ModalList = ({ socket }) => {
    const [show, setShow] = useState(false);
    const handleClose = () => setShow(false);
    const handleShow = () => setShow(true);
    const [lists, setlist] = useState([]);
    const fetchFact = () => {
        fetch("http://myapi/getList")
            .then((response) => response.json())
            .then((data) => setlist(data));
    }
    useEffect(() => {
        fetchFact()
    }, []);

    return (
        <div className='container'>
            {lists.map(singleobject => (
                <div>
                    <div>{singleobject.title}</div>
                    <div>{singleobject.listofelement.join(', ')}</div>
                    <div>
                        <Button variant="primary" onClick={handleShow}>
                            {singleobject.title}
                        </Button>
                        <Modal show={show} onHide={handleClose}>
                            <Modal.Header closeButton>
                                <Modal.Title>{singleobject.title}</Modal.Title>
                            </Modal.Header>
                            <Modal.Body>{singleobject.listofelement.join(', ')}</Modal.Body>
                            <Modal.Footer>
                                <Button variant="secondary" onClick={handleClose}>
                                    Close
                                </Button>
                                <Button variant="primary" onClick={handleClose}>
                                    Save
                                </Button>
                            </Modal.Footer>
                        </Modal></div>
                </div>
            ))}
        </div>
    );
}

export default ModalList;

解决方案

问题根源

  1. 共用状态导致同步显示:所有Modal绑定同一个show状态,点击任意按钮会触发所有Modal渲染,最后一个Modal会覆盖前面的,看起来只显示最后一条数据。
  2. 闭包变量捕获异常:循环中的singleobject在闭包中被后续迭代覆盖,Modal最终渲染时,所有引用都指向最后一个元素。
  3. 字段名不匹配:服务器返回字段是Title和Listofitems,但客户端用了title和listofelement,导致数据无法正确读取。

修复方法

方法一:用状态存储当前选中对象

只维护一个Modal,点击按钮时记录当前选中的对象,Modal根据该对象渲染内容:

import { React, useEffect, useState } from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';

const ModalList = ({ socket }) => {
    const [show, setShow] = useState(false);
    const [currentItem, setCurrentItem] = useState(null);
    const [lists, setlist] = useState([]);

    const handleClose = () => {
        setShow(false);
        setCurrentItem(null);
    };
    const handleShow = (item) => {
        setCurrentItem(item);
        setShow(true);
    };

    const fetchFact = () => {
        fetch("http://myapi/getList")
            .then((response) => response.json())
            .then((data) => setlist(data));
    };

    useEffect(() => {
        fetchFact();
    }, []);

    return (
        <div className='container'>
            {lists.map((singleobject, index) => (
                <div key={index}>
                    <div>{singleobject.Title}</div>
                    <div>{singleobject.Listofitems.join(', ')}</div>
                    <div>
                        <Button variant="primary" onClick={() => handleShow(singleobject)}>
                            {singleobject.Title}
                        </Button>
                    </div>
                </div>
            ))}

            {currentItem && (
                <Modal show={show} onHide={handleClose}>
                    <Modal.Header closeButton>
                        <Modal.Title>{currentItem.Title}</Modal.Title>
                    </Modal.Header>
                    <Modal.Body>{currentItem.Listofitems.join(', ')}</Modal.Body>
                    <Modal.Footer>
                        <Button variant="secondary" onClick={handleClose}>
                            Close
                        </Button>
                        <Button variant="primary" onClick={handleClose}>
                            Save
                        </Button>
                    </Modal.Footer>
                </Modal>
            )}
        </div>
    );
};

export default ModalList;

方法二:将Modal抽成独立组件

把按钮和对应Modal封装成独立组件,每个组件维护自己的show状态,避免闭包问题:

import { React, useEffect, useState } from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';

const ItemModal = ({ item }) => {
    const [show, setShow] = useState(false);
    const handleClose = () => setShow(false);
    const handleShow = () => setShow(true);

    return (
        <div>
            <div>{item.Title}</div>
            <div>{item.Listofitems.join(', ')}</div>
            <Button variant="primary" onClick={handleShow}>
                {item.Title}
            </Button>
            <Modal show={show} onHide={handleClose}>
                <Modal.Header closeButton>
                    <Modal.Title>{item.Title}</Modal.Title>
                </Modal.Header>
                <Modal.Body>{item.Listofitems.join(', ')}</Modal.Body>
                <Modal.Footer>
                    <Button variant="secondary" onClick={handleClose}>
                        Close
                    </Button>
                    <Button variant="primary" onClick={handleClose}>
                        Save
                    </Button>
                </Modal.Footer>
            </Modal>
        </div>
    );
};

const ModalList = ({ socket }) => {
    const [lists, setlist] = useState([]);

    const fetchFact = () => {
        fetch("http://myapi/getList")
            .then((response) => response.json())
            .then((data) => setlist(data));
    };

    useEffect(() => {
        fetchFact();
    }, []);

    return (
        <div className='container'>
            {lists.map((item, index) => (
                <ItemModal key={index} item={item} />
            ))}
        </div>
    );
};

export default ModalList;

额外注意点

  • 循环渲染必须添加key属性,避免React渲染异常。
  • 统一字段名:确保客户端使用的字段和服务器返回一致,或在数据获取时做格式转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 14:45:30