I’m working on a simple react UI which uses react-router-dom for handling the pages and loads some iframes.
At the moment everything works, but, everytime a user navigate back and forth a page containing and iframe, it gets rerendered. My goal is to avoid that and let the users see the iframe as it was before switching pages.
To be more clear, follow these steps:
- click on "Page with iframe"
- The home of wikipedia is shown into the iframe
- scroll or navigate to some random page into wikipedia’s iframe
- click on "Page with content"
- click on "Page with iframe"
Current behavior: The iframe is reloaded and wikipedia’s home is shown again
Desired behavior: The iframe is shown exactly as it was left before leaving the page
I’ve created this small react example in a sandbox: https://codesandbox.io/s/eloquent-cache-2s9ddn?file=/src/App.js
Here is the code for reference:
import React, { useEffect, useState } from "react";
import { BrowserRouter as Router, Route, Routes, Link } from "react-router-dom";
function delay(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
const fakeApi = async () => {
await delay(1000);
return {
src: "https://fr.wikipedia.org/wiki/Main_Page"
};
};
const Page1 = () => <div>Page with sample content</div>;
const Page2 = () => {
const [iframeUrl, setIframeUrl] = useState(null);
const loadIframe = async () => {
const { src } = await fakeApi();
setIframeUrl(src);
};
useEffect(() => {
loadIframe();
}, []);
return (
<div>
<h3>Page with sample iframe</h3>
<p>
Eveytime a users moves to this page the iframe is reloaded (ex. if you
try to scroll, navigate to "Page with content" and back to "Page with
iframe", you'll see a new iframe is loaded)
</p>
<iframe src={iframeUrl} width="640" height="480" title="test wikipedia" />
</div>
);
};
export default () => (
<Router>
<ul>
<li>
<Link to="/contentpage">Page with content</Link>
</li>
<li>
<Link to="/iframepage">Page with iframe</Link>
</li>
</ul>
<hr />
<Routes>
<Route exact path="/contentpage" element={<Page1 />} />
<Route path="/iframepage" element={<Page2 />} />
</Routes>
</Router>
);
2
Answers
I found a solution, basically I will need to pull the page out of the react-router-dom library and route it manually.
It's kind of an hacky fix but consider the huge improvement I've on speed and usability of the whole UI, I'm willing to take this compromises.
Here is the working example: https://codesandbox.io/s/optimistic-rgb-mmqyss?file=/src/App.js
And just in case it will ever go down and somebody will still need the solution, here is the code:
The content of the iFrame has no state in React, so gets reset when your rerender it. You need to render everything on the page once and then use CSS to hide and show the content.