如何避免页面刷新后显示路由状态数据?React技术问题咨询
To fix the issue where the success alert persists on page refresh, you need to clear the location state from the browser's history entry after using it. Directly mutating location.state is not recommended (it's immutable in React Router), so instead use navigate to replace the current history entry without the state. Here's the corrected component A code:
import { useLocation, useNavigate } from 'react-router-dom'; import { useState, useEffect } from 'react'; export function A() { const [showAlert, setShowAlert] = useState(false); const [alertMessage, setAlertMessage] = useState(''); const location = useLocation(); const navigate = useNavigate(); useEffect(() => { const successMsg = location.state?.data; if (successMsg) { // Store the message locally so we can display it after clearing the state setAlertMessage(successMsg); setShowAlert(true); // Replace the current history entry to remove the state // This ensures a page refresh won't re-read the state navigate('/', { replace: true, state: null }); // Auto-hide the alert after 8 seconds const timer = setTimeout(() => { setShowAlert(false); setAlertMessage(''); }, 8000); // Clean up the timer if the component unmounts early return () => clearTimeout(timer); } }, [location.state, navigate]); return ( <div> {showAlert && <div className="alert">{alertMessage}</div>} {/* Your component A content here */} </div> ); } export default A;
Key Changes & Explanations:
- Store Alert Message Locally: We capture the success message from
location.stateand store it inalertMessagestate. This way, we can still display it after clearing the location state. - Replace History Entry: Using
navigate('/', { replace: true, state: null })replaces the current history entry with a new one that has no state. This means when the page is refreshed, there's no state to trigger the alert. - Proper Cleanup: The timeout is cleared in the useEffect cleanup function to prevent memory leaks if the component unmounts before the alert hides.
- Fix Typos: Corrected
formtofromin the import, and ensured we export component A instead of B.
Alternative Approach (Using Session Storage):
If you prefer not to modify the history stack, you can use session storage to track whether the alert has already been shown:
import { useLocation } from 'react-router-dom'; import { useState, useEffect } from 'react'; export function A() { const [showAlert, setShowAlert] = useState(false); const [alertMessage, setAlertMessage] = useState(''); const location = useLocation(); useEffect(() => { const successMsg = location.state?.data; const alertShown = sessionStorage.getItem('alertShown'); if (successMsg && !alertShown) { setAlertMessage(successMsg); setShowAlert(true); sessionStorage.setItem('alertShown', 'true'); const timer = setTimeout(() => { setShowAlert(false); setAlertMessage(''); sessionStorage.removeItem('alertShown'); }, 8000); return () => clearTimeout(timer); } }, [location.state]); return ( <div> {showAlert && <div className="alert">{alertMessage}</div>} {/* Your component A content here */} </div> ); } export default A;
This approach uses session storage to mark the alert as shown, so it won't trigger again on refresh. Note that this will persist across tabs/windows in the same session, which may or may not be desired.
内容的提问来源于stack exchange,提问作者user3450590

