如何实现React中Axios请求仅在点击打开Bootstrap Modal时触发
问题根因
你当前的代码提前发起请求的核心原因有两个:
<ComparisonModal>组件是随父页面一同渲染挂载的,而你写的空依赖数组的useEffect会在组件挂载完成后立刻执行,所以无论用户是否点击打开模态框,请求都会在页面加载时直接触发。- 你用了Bootstrap原生的
data-bs-*属性控制模态框显隐,React层无法感知模态框的开关状态,没法和请求逻辑做联动。
最优实现方案
推荐用React状态控制模态框的显隐逻辑,配合条件渲染实现请求按需触发,完整实现步骤如下:
1. 父组件新增状态管理
父组件新增两个状态,分别控制模态框是否展示、存储当前选中的行ID:
// 父组件顶部引入useState import { useState } from 'react'; // 父组件内部定义状态 const [showModal, setShowModal] = useState(false); const [selectedRowId, setSelectedRowId] = useState(null); // 改造rowEvents方法 const rowEvents = (id) => { setSelectedRowId(id); setShowModal(true); // 原有rowEvents的其他逻辑保留 };
修改触发按钮的代码,删掉原生的data-bs-*控制属性:
<td> <button type="button" onClick={() => rowEvents(id)}> Compare </button> </td>
父组件渲染模态框的位置改成条件渲染,只有showModal为true时才加载Modal组件:
{ showModal && <ComparisonModal previousWon={previousWon} currentWon={currentWon} rowId={selectedRowId} onClose={() => setShowModal(false)} /> }
2. 改造ComparisonModal组件
在Modal组件内初始化Bootstrap模态框实例,监听关闭事件同步父组件状态,同时保留你的请求逻辑:
import { useEffect, useRef } from 'react'; import * as bootstrap from 'bootstrap'; const ComparisonModal = ({ previousWon, currentWon, rowId, onClose }) => { const modalRef = useRef(null); const modalInstanceRef = useRef(null); // 初始化模态框实例,监听关闭事件 useEffect(() => { modalInstanceRef.current = new bootstrap.Modal(modalRef.current); modalInstanceRef.current.show(); // 同步模态框原生关闭事件到父组件 const handleModalClose = () => onClose(); modalRef.current.addEventListener('hidden.bs.modal', handleModalClose); // 组件销毁时清理实例和事件 return () => { modalRef.current.removeEventListener('hidden.bs.modal', handleModalClose); modalInstanceRef.current?.dispose(); }; }, [onClose]); // 请求逻辑,只有组件挂载(用户点击打开模态框)时才会触发 useEffect(() => { async function fetchData() { // 可以用传入的rowId发起对应请求 const content = await client.get(`你的接口地址/${rowId}`); // 后续处理返回数据的逻辑保留 } fetchData(); }, [rowId]); return ( <div className="modal fade" ref={modalRef} data-bs-backdrop="static" data-bs-keyboard="false" tabIndex="-1" aria-hidden="true" > {/* 你原有模态框的modal-dialog、modal-content等内容全部保留 */} </div> ); }; export default ComparisonModal;
其他可选方案
如果你不需要每次打开模态框都重新加载组件,可以不用条件渲染,直接给Modal组件传入show状态,把show加入请求useEffect的依赖即可:
// Modal组件内的请求逻辑改造 useEffect(() => { if (!show) return; // 模态框未打开时不发起请求 async function fetchData() { const content = await client.get('1'); } fetchData(); }, [show]);
内容的提问来源于stack exchange,提问作者Ilyas Patel
相关产品推荐
相关产品推荐

