React如何在App类组件中使用Modal组件及封装自定义模态框
实现步骤
1. 调整App组件逻辑
首先在App组件的state中新增模态框控制与编辑数据存储字段,补充编辑、保存、关闭模态框的相关方法,修正原代码中DOM属性使用错误(React中使用className代替原生class)、table结构错误问题。
修改后的App组件代码如下:
import React, { Component } from 'react'; import EditModal from './EditModal'; // 引入后面封装的自定义模态框组件 class App extends Component { state = { lists: [], isModalOpen: false, // 控制模态框显隐 editingItem: null // 存储当前待编辑的行数据 } componentDidMount() { fetch('URL') .then(res => res.json()) .then((data) => { this.setState({ lists: data }) }) .catch(console.log) } // 点击编辑按钮触发 handleEdit = (item) => { this.setState({ editingItem: item, isModalOpen: true }) } // 保存编辑后的数据 handleSaveEdit = (updatedItem) => { const newLists = this.state.lists.map(item => item.orderNo === updatedItem.orderNo ? updatedItem : item ) this.setState({ lists: newLists, isModalOpen: false, editingItem: null }) // 此处可补充编辑结果提交后端接口的逻辑 } // 关闭模态框 handleCloseModal = () => { this.setState({ isModalOpen: false, editingItem: null }) } render() { return ( <div className="container"> <table className="table-sm"> <thead className="thead-dark"> <tr className="table-bordered"> <th>Order Number</th> <th>Delivery Date</th> <th>Customer</th> <th>Tracking number</th> <th>Status</th> <th>Consignee</th> <th>Edit</th> <th>Delete</th> </tr> </thead> <tbody className="table-bordered"> {this.state.lists.map(listInfo => ( <tr key={listInfo.orderNo}> <td>{listInfo.orderNo}</td> <td>{listInfo.date}</td> <td>{listInfo.customer}</td> <td>{listInfo.trackingNo}</td> <td>{listInfo.status}</td> <td>{listInfo.consignee}</td> <td> <button type="button" className="btn btn-primary" onClick={() => this.handleEdit(listInfo)} > 编辑 </button> </td> <td><button className="btn btn-danger">删除</button></td> </tr> ))} </tbody> </table> {/* 引入自定义模态框组件,传入对应参数 */} <EditModal visible={this.state.isModalOpen} editData={this.state.editingItem} onClose={this.handleCloseModal} onSave={this.handleSaveEdit} /> </div> ); } } export default App;
2. 封装自定义模态框组件
新建EditModal.js文件,编写独立可复用的模态框组件,所有交互逻辑通过props和父组件通信:
import React, { Component } from 'react'; class EditModal extends Component { state = { // 初始化表单数据 formData: { orderNo: '', date: '', customer: '', trackingNo: '', status: '', consignee: '' } } // 监听编辑数据变化,更新表单 componentDidUpdate(prevProps) { if (prevProps.editData !== this.props.editData && this.props.editData) { this.setState({ formData: this.props.editData }) } } // 表单输入同步 handleInputChange = (e) => { const { name, value } = e.target; this.setState(prev => ({ formData: { ...prev.formData, [name]: value } })) } // 提交保存 handleSubmit = () => { this.props.onSave(this.state.formData) } render() { const { visible, onClose } = this.props; const { formData } = this.state; if (!visible) return null; return ( <div className="modal fade show" style={{display: 'block'}} tabIndex="-1" role="dialog"> <div className="modal-dialog" role="document"> <div className="modal-content"> <div className="modal-header"> <h5 className="modal-title">编辑订单信息</h5> <button type="button" className="close" onClick={onClose}> <span>×</span> </button> </div> <div className="modal-body"> <div className="form-group"> <label>订单号</label> <input type="text" className="form-control" name="orderNo" value={formData.orderNo} onChange={this.handleInputChange} disabled /> </div> <div className="form-group"> <label>交货日期</label> <input type="date" className="form-control" name="date" value={formData.date} onChange={this.handleInputChange} /> </div> {/* 剩余字段按照上面的格式补充即可 */} <div className="form-group"> <label>客户</label> <input type="text" className="form-control" name="customer" value={formData.customer} onChange={this.handleInputChange} /> </div> </div> <div className="modal-footer"> <button type="button" className="btn btn-secondary" onClick={onClose}>取消</button> <button type="button" className="btn btn-primary" onClick={this.handleSubmit}>保存</button> </div> </div> </div> </div> ) } } export default EditModal;
3. 全局调用模态框的实现
如果需要在index.js中直接调用该模态框(不依附于App组件的层级),可以使用React的createPortal方法将模态框挂载到全局body节点,示例如下:
// index.js 中修改 import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; import EditModal from './EditModal'; // 如果需要全局控制模态框,可以单独维护模态框的状态 const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> {/* 全局挂载的模态框,可通过全局状态/事件总线控制显隐 */} {/* <EditModal visible={globalModalVisible} ...其他props /> */} </React.StrictMode> );
内容的提问来源于stack exchange,提问作者Vahid Afshari
相关产品推荐
相关产品推荐

