Memory Router无法触发浏览器返回按钮?React Router 4.2.2方案咨询
Great question! Let’s break this down clearly and give you practical solutions:
First, the core truth: MemoryRouter does NOT natively support the browser’s back/forward buttons. Here’s why, and how you can fix this:
Why the Back Button Isn’t Working
MemoryRouter is designed to manage routing history entirely in memory—completely separate from the browser’s native window.history stack. This makes it ideal for non-browser environments (like unit tests, Node.js apps, or embedded widgets) where you don’t want to modify the actual browser history. But because it doesn’t sync with the browser’s history, clicking the back button won’t trigger any changes in your MemoryRouter-driven app.
Solutions to Get Browser Back Button Functionality
1. Switch to BrowserRouter or HashRouter (Recommended)
If your app runs in a browser and you need native back/forward support, this is the simplest and most reliable approach. Both BrowserRouter and HashRouter automatically sync with the browser’s history stack, so the back button will work exactly as expected without extra code.
Just replace your MemoryRouter with BrowserRouter:
import { BrowserRouter, Route } from 'react-router-dom'; <BrowserRouter> <div> <Route path="/one" component={FirstPage} /> <Route path="/two" component={SecondPage} /> </div> </BrowserRouter>
Your existing this.props.history.push('/two') logic will still work perfectly, and now clicking the browser’s back button will take you back to /one seamlessly.
2. Manual Sync (Only if You Must Use MemoryRouter)
If you have a specific reason to stick with MemoryRouter (e.g., custom history logic for testing), you can manually sync the browser’s popstate events with MemoryRouter’s in-memory history. This requires extra code to handle synchronization:
Step 1: Listen to Browser Popstate Events
Wrap your MemoryRouter in a component that listens for back/forward events and updates the MemoryRouter’s history:
import { MemoryRouter, Route } from 'react-router-dom'; import { useRef, useEffect } from 'react'; function AppWithSyncedHistory() { const memoryHistoryRef = useRef(); useEffect(() => { const handlePopState = () => { // Get the current path from the browser const currentPath = window.location.pathname; // Sync it to MemoryRouter's history memoryHistoryRef.current?.replace(currentPath); }; window.addEventListener('popstate', handlePopState); // Clean up the listener when the component unmounts return () => window.removeEventListener('popstate', handlePopState); }, []); return ( <MemoryRouter initialEntries={['/one', '/two']} ref={memoryHistoryRef} > <div> <Route path="/one" component={FirstPage} /> <Route path="/two" component={SecondPage} /> </div> </MemoryRouter> ); }
Step 2: Update Browser History When Navigating
When you call history.push in your components, you also need to manually add an entry to the browser’s history stack:
// Inside your component's navigation logic this.props.history.push('/two'); // Manually update the browser's history window.history.pushState({}, '', '/two');
⚠️ Note: This approach requires you to handle edge cases like duplicate history entries, stack length management, and consistency between in-memory and browser history. It’s not ideal for most production apps, so use it only if you have no other option.
Final Takeaway
MemoryRouter is not built for browser history integration. For most browser-based apps, BrowserRouter is the right tool for the job and gives you native back/forward support out of the box. Only resort to manual sync if you have a specific constraint forcing you to use MemoryRouter.
内容的提问来源于stack exchange,提问作者kpwahn

