'CSS crashes when I reload page
I am building a site with Gatsby. I am using a component that imports a script and returns a form. The problem is, that after you loaded the page that shows the form, and then you click to any other page and go back to that form page, the css fully crashes for the entire site and you have to refresh the whole page. To check out what I mean click this link https://baerenherz.org/, go to the dark blue button on the very right of the menu, then click to any other navigation site and then click again on the blue button (jetzt-spenden).
Here is my component for the donation form :
import React, { useState, useEffect } from "react"
import {Helmet} from "react-helmet"
import Loading from "./Loading"
function Child() {
return(
<div style={{width: "75%", margin: "4em auto"}} >
<Helmet>
<script type='text/javascript' aysnc>
{` window.rnw.tamaro.runWidget('.dds-widget-container', {language: 'de'}) `}
</script>
</Helmet>
<div className="dds-widget-container"></div>
</div>
)
}
function RaiseNow() {
const [loaded, setLoaded] = useState(false)
useEffect(() => {
const scriptTag = document.createElement('script')
scriptTag.src='https://tamaro.raisenow.com/xxx/latest/widget.js'
scriptTag.addEventListener('load', ()=> setLoaded(true))
document.body.appendChild(scriptTag)
return ()=>{
scriptTag.removeEventListener(); // check if necessary
setLoaded(false) // check if necessary
}
}, []);
return (
<>
{loaded ? <Child /> : <Loading/>}
</>
)
}
export default RaiseNow
What I noticed is, that the second time you visit the page, the Loading.... component does not even show anymore.. the Layout is displayed but as soon as the form shows, it crashes...
Since I cannot solve this issue since literally last year I would really appreciate any help with this. Thank you in advance.
Solution 1:[1]
Apparently, your script is breaking React's hydration when the component should be mounted/unmounted. There's no "clean" solution if there's no React-based script available. The problem here is that your script is manipulating the DOM while React manages the virtual DOM (vDOM). Changes in the DOM outside React's scope are not listened to by React and vice versa.
That said, I'd try forcing the loading and rendering of your widget each time the page loads. Something like:
function RaiseNow() {
const [loaded, setLoaded] = useState(false)
useEffect(() => {
const scriptTag = document.createElement('script')
scriptTag.src='https://tamaro.raisenow.com/xxx/latest/widget.js'
scriptTag.addEventListener('load', ()=> setLoaded(true))
document.body.appendChild(scriptTag)
window.rnw.tamaro.runWidget('.dds-widget-container', {language: 'de'})
return ()=>{
scriptTag.removeEventListener('load', setLoaded(false)); // check if necessary
setLoaded(false) // check if necessary
}
}, []);
return (
<>
{loaded ? <Child /> : <Loading/>}
</>
)
}
export default RaiseNow
Without a CodeSandbox it's difficult to guess how the code will behave but what it's important is to detach and clean up the listeners when the component is removed from the UI to avoid breaking React's hydration process, in the return statement. From the useEffect docs:
The clean-up function runs before the component is removed from the UI to prevent memory leaks. Additionally, if a component renders multiple times (as they typically do), the previous effect is cleaned up before executing the next effect. In our example, this means a new subscription is created on every update. To avoid firing an effect on every update, refer to the next section.
There, besides removing the listeners from the script, you can also set the loading state to false.
I've also removed the second useEffect because the idea to avoid the CSS breaking is to force the loading of the script in each page rendering. It's not an optimal solution but it may work for you. The ideal solution would be using React-based dependencies.
Another thing to take into account is to delay the trigger of your rnw.tamaro script until the DOM tree is loaded, by moving it from the Helmet to the useEffect. This should ensure that your div and the window are available.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
