React非关联组件函数调用:如何在ProductModals中调用fetchData?
React子组件提交后刷新另一个子组件数据的解决方案
问题场景
现有React项目包含三个组件:viewProduct(父组件)、ProductTable、ProductModals。其中ProductTable内部有fetchData函数用于获取产品列表数据;ProductModals表单提交完成后,需要调用该fetchData函数刷新产品数据。
推荐两种可行实现方案,优先选择第一种状态提升方案:
方案一:状态提升+回调函数(推荐)
将产品数据和数据获取逻辑统一移到父组件viewProduct中,通过props传递数据给ProductTable,同时给ProductModals传递提交成功后的回调函数,触发数据刷新。
1. 修改父组件 viewProduct.js
import React, { useEffect, useState } from "react"; import ProductTable from "../../Components/Tables/Product/ProductTable"; import ProductModals from "../../Components/Modals/Product/ProductModals"; import axios from 'axios'; function viewProduct() { // 父组件维护产品数据状态 const [productData, setProductData] = useState([]); // 统一的获取数据函数 const fetchData = () => { axios .get("http://localhost:4000/api/products/product/viewAllProduct") .then((res) => { setProductData(res.data.data); }) .catch(err => console.error('获取产品数据失败:', err)); }; // 初始化加载数据 useEffect(() => { fetchData(); }, []); // 提交成功后触发数据刷新的回调 const handleSubmitSuccess = () => { fetchData(); }; return ( <> <ProductModals onSubmitSuccess={handleSubmitSuccess} /> <ProductTable data={productData} /> </> ); } export default viewProduct;
2. 修改 ProductTable.js
移除内部状态和fetchData,直接使用父组件传递的数据渲染:
import React from "react"; function ProductTable({ data }) { // 直接使用props传入的data进行渲染 return ( // 你的表格JSX代码,示例: <table> <thead> <tr> <th>产品名称</th> <th>价格</th> </tr> </thead> <tbody> {data.map(product => ( <tr key={product.id}> <td>{product.name}</td> <td>{product.price}</td> </tr> ))} </tbody> </table> ); } export default ProductTable;
3. 修改 ProductModals.js
接收父组件传递的回调,在表单提交成功后调用:
import React, { useState } from "react"; import axios from 'axios'; function ProductModals({ onSubmitSuccess }) { const [formData, setFormData] = useState({ name: '', price: '' }); const handleSubmit = (e) => { e.preventDefault(); // 表单提交逻辑 axios.post("http://localhost:4000/api/products/product/addProduct", formData) .then(() => { console.log('提交成功'); // 触发父组件的刷新回调 onSubmitSuccess(); // 这里可以添加关闭模态框等后续操作 }) .catch(err => console.error('提交失败:', err)); }; return ( // 你的模态框JSX代码,示例: <div className="modal"> <form onSubmit={handleSubmit}> <input type="text" value={formData.name} onChange={(e) => setFormData({...formData, name: e.target.value})} placeholder="产品名称" /> <input type="number" value={formData.price} onChange={(e) => setFormData({...formData, price: e.target.value})} placeholder="价格" /> <button type="submit">提交</button> </form> </div> ); } export default ProductModals;
方案优势
- 符合React单向数据流原则,数据统一由父组件管理,避免子组件间耦合
- 子组件职责单一:
ProductTable仅负责渲染,ProductModals仅负责表单提交 - 代码易维护,后续修改数据逻辑只需在父组件调整
方案二:使用Ref调用子组件方法(不推荐)
通过React的ref获取ProductTable组件实例,直接调用其内部的fetchData方法。这种方式会破坏组件封装性,仅在特殊场景下使用。
1. 修改父组件 viewProduct.js
import React, { useRef } from "react"; import ProductTable from "../../Components/Tables/Product/ProductTable"; import ProductModals from "../../Components/Modals/Product/ProductModals"; function viewProduct() { const tableRef = useRef(null); const handleSubmitSuccess = () => { // 调用子组件的fetchData方法 tableRef.current?.fetchData(); }; return ( <> <ProductModals onSubmitSuccess={handleSubmitSuccess} /> <ProductTable ref={tableRef} /> </> ); } export default viewProduct;
2. 修改 ProductTable.js
使用forwardRef和useImperativeHandle暴露内部方法:
import React, { useEffect, useState, forwardRef, useImperativeHandle } from "react"; import axios from 'axios'; const ProductTable = forwardRef((props, ref) => { const [data, setData] = useState([]); const fetchData = () => { axios .get("http://localhost:4000/api/products/product/viewAllProduct") .then((res) => { setData(res.data.data); }) .catch(err => console.error('获取数据失败:', err)); }; useEffect(() => { fetchData(); }, []); // 暴露fetchData给父组件的ref useImperativeHandle(ref, () => ({ fetchData })); return ( // 你的表格JSX代码 ); }); export default ProductTable;
3. 修改 ProductModals.js
同方案一,接收onSubmitSuccess回调并在提交后调用即可。
方案缺点
- 父组件依赖子组件内部实现,子组件修改方法名或逻辑时,父组件需同步调整
- 破坏组件封装性,违反React组件设计原则
内容的提问来源于stack exchange,提问作者programming Digital
相关产品推荐
相关产品推荐

