添加新行后React Table未更新:如何通过React Hooks在CRUD操作后刷新MailList表格
Great question! The key here is leveraging React's one-way data flow and state lifting to trigger a refresh in your MailList component after a successful POST from AddMail. Here's a step-by-step solution tailored to your code:
Step 1: Lift state to the parent component
Move the "refresh trigger" logic to the parent component that renders both MailList and AddMail. This lets the parent coordinate the refresh between the two children.
// Parent component (e.g., MailDashboard.jsx) import MailList from './MailList'; import AddMail from './AddMail'; import { useState } from 'react'; export default function MailDashboard() { // Use a counter as a refresh trigger – incrementing it will trigger a re-fetch const [refreshTrigger, setRefreshTrigger] = useState(0); // Function to trigger refresh (passed to AddMail) const handleRefresh = () => { setRefreshTrigger(prev => prev + 1); }; return ( <div> <AddMail onRefresh={handleRefresh} /> <MailList refreshTrigger={refreshTrigger} /> </div> ); }
Step 2: Update MailList to respond to the refresh trigger
Modify MailList to accept the refreshTrigger prop, and use it as a dependency in your useEffect to re-fetch data whenever the trigger changes. We'll also extract the fetch logic into a reusable function for clarity:
// MailList.jsx import axios from 'axios'; import { useState, useEffect } from 'react'; // Ensure your Material UI components (Title, Table, etc.) are imported export default function MailList({ refreshTrigger }) { const [mailList, setMailList] = useState([]); // Extract fetch logic into a reusable function const fetchMailList = () => { axios.get("http://localhost:5243/api/Mail") .then(res => { setMailList(res.data); console.log(res.data); }) .catch(err => console.log(err)); }; // Re-run fetch whenever refreshTrigger changes useEffect(() => { fetchMailList(); }, [refreshTrigger]); return( <React.Fragment> <Title>Recent Mail Scanned</Title> <Table> <TableHead> <TableRow> <TableCell>ID</TableCell> <TableCell>Tracking Number</TableCell> <TableCell>Date Scanned</TableCell> </TableRow> </TableHead> <TableBody> {mailList.map((m) => ( <TableRow key={m.mailId}> <TableCell>{m.mailId}</TableCell> <TableCell>{m.trackingNo}</TableCell> <TableCell>{m.dateScanned}</TableCell> </TableRow> ))} </TableBody> </Table> </React.Fragment> ); }
Step 3: Trigger refresh from AddMail after successful POST
Update AddMail to accept the onRefresh prop, and call it only after the POST request succeeds. We'll also fix a minor issue with your item variable (declare it inside the addMail function to get the latest form values):
// AddMail.jsx import axios from 'axios'; import { useState } from 'react'; // Ensure your Button and form components are imported const initialValues = { trackingNumber: '', dateCreated: new Date(), }; export default function AddMail({ onRefresh }) { const [values, setValues] = useState(initialValues); const handleInputChange = e => { const { name, value } = e.target; setValues({ ...values, [name]: value }); }; const addMail = () => { // Declare item inside the function to capture the latest form values const item = { trackingNo: values.trackingNumber, dateCreated: values.dateCreated }; axios.post("http://localhost:5243/api/Mail", item ) .then(() => { // Trigger refresh only after successful POST onRefresh(); // Optional: Reset form after save setValues(initialValues); }) .catch(err => console.log(err)); }; return ( <div> {/* Your form inputs go here – example input for tracking number */} <input name="trackingNumber" value={values.trackingNumber} onChange={handleInputChange} placeholder="Enter tracking number" /> <Button onClick={addMail}>Save Mail</Button> </div> ); }
Why this works
- State lifting: The parent component acts as the single source of truth for the refresh signal, keeping the data flow predictable.
- Trigger-based re-fetch: The
refreshTriggercounter ensuresMailListonly re-fetches data when a successful POST happens, avoiding unnecessary API calls. - Error safety: We only trigger the refresh after the POST request succeeds, so your table won't refresh if the API call fails.
Alternative options (for larger apps)
If your component tree is deeply nested, you could use React Context to pass the refresh function instead of prop-drilling. For small datasets, you could also return the newly created mail item from your POST endpoint and add it directly to the mailList state (instead of re-fetching the entire list), but re-fetching is more reliable for keeping data in sync with the backend.
内容的提问来源于stack exchange,提问作者Killua

