Hey @mipaca
I know you answered your own question already, but I did some experimentation of my own and wanted to share my findings in case its helpful:
I too have been curious about how React Router works with Webflow.
What I quickly remembered is that React Router was designed for single page apps.
It’s expecting your pages to be React components and not actual html pages that Webflow generates.
This is why you can mount an entire React app inside of a Webflow page and have the routing logic work as expected, but the second you refresh the site on a path that doesn’t actually exist in Webflow, you’ll get a PAGE NOT FOUND error.
My workaround, without relying on hash routes, was to think in the Single Page App paradigm and apply it as best as possible to Webflow. What that looks like is basically:
- making sure that each Route in React Router actually exists on Webflow
- mounting identical react apps in the same place on every Webflow page using the routing logic
This is absolutely a hack and not recommended - just a proof of concept.
Ideally, you’d reserve Single Page Routing for Single Page Apps, and optimize your React app to work in a multi page setting like Webflow.
Here’s my demo link to play around with it:
https://test-site-react.webflow.io/
If you want to rapidly prototype with this on your site, here’s the code:
<!-- Load React, ReactDOM -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<!-- Load Babel (test purposes only) -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- Load history -->
<script src="https://unpkg.com/history@5/umd/history.development.js" crossorigin></script>
<!-- Load React Router and React Router DOM -->
<script src="https://unpkg.com/react-router@6/umd/react-router.development.js" crossorigin></script>
<script src="https://unpkg.com/react-router-dom@6/umd/react-router-dom.development.js" crossorigin></script>
<script type="text/babel" data-type="module">
var BrowserRouter = ReactRouterDOM.BrowserRouter;
var Routes = ReactRouterDOM.Routes;
var Route = ReactRouterDOM.Route;
var Link = ReactRouterDOM.Link;
const usePrevious = (value) => {
const ref = React.useRef()
React.useEffect(() => { ref.current = value })
return ref.current
}
const useLocationChange = (action) => {
const location = ReactRouterDOM.useLocation();
const prevLocation = usePrevious(location)
React.useEffect(() => {
action(location, prevLocation)
}, [location])
}
function App() {
const [currentPath, setCurrentPath] = React.useState('')
const [prevPath, setPrevPath] = React.useState('')
useLocationChange((location, prevLocation) => {
console.log('changed from', prevLocation, 'to', location)
setCurrentPath(location?.pathname)
setPrevPath(prevLocation?.pathname)
})
return (
<div>
<h1>React Router, Tailwind & Babel on Webflow!</h1>
<p>Previous Path: {prevPath} || Current Path: {currentPath}</p>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</div>
);
}
function Home() {
return (
<>
<main>
<h2>Homepage!</h2>
<p>This component renders on the '/' path.</p>
</main>
<nav>
<Link to="/about">About</Link>
</nav>
</>
);
}
function About() {
return (
<>
<main>
<h2>About page</h2>
<p>
This component should only render on the '/about' path (but not on the actual '/about' page)
</p>
</main>
<nav>
<Link to="/">Home</Link>
</nav>
</>
);
}
const container = document.getElementById('app');
ReactDOM.createRoot(container).render(
<BrowserRouter>
<App />
</BrowserRouter>
);
</script>
Make sure to create a div with the id “app” so you can mount this properly…
Also make to either create an “/about” page or update the Routes with your own pages that you want to test