I have an express server that uses Server Side Rendering (SSR) to render a react app.
I want to use the materialize-css
package together with my react app.
I have imported the materialize-css/dist/css/materialize.min.css
and materialize-css/dist/js/materialize.min
into my App.js.
Before I used express to render my app server side it worked fine, styling and modals from materialize was loaded correctly.
Now when I try to render my app using express, I get following error:
[0] ReferenceError: window is not defined
[0] at Object.<anonymous> (/Users/user/Sites/task_keeper/node_modules/materialize-css/dist/js/materialize.min.js:6:1135)
[0] at Module._compile (internal/modules/cjs/loader.js:778:30)
[0] at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
[0] at Module.load (internal/modules/cjs/loader.js:653:32)
[0] at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
[0] at Function.Module._load (internal/modules/cjs/loader.js:585:3)
[0] at Module.require (internal/modules/cjs/loader.js:692:17)
[0] at require (internal/modules/cjs/helpers.js:25:18)
[0] at eval (webpack:///external_%22materialize-css/dist/js/materialize.min%22?:1:18)
This is my render middleware:
const renderMiddleware = () => (req, res) => {
let html = req.html;
const htmlContent = ReactDOMServer.renderToString(<App />);
const htmlReplacements = {
HTML_CONTENT: htmlContent,
};
Object.keys(htmlReplacements).forEach(key => {
const value = htmlReplacements[key];
html = html.replace(
new RegExp('__' + escapeStringRegexp(key) + '__', 'g'),
value
);
});
res.send(html);
};
And then I use hydrate in index.js
,
ReactDOM.hydrate(<App />, document.getElementById('root'));.
What is the correct way to use materialize-css
in a setup like this?
You can solve this by loading the script with a CDN, like this:
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
This way the script is injected into the window
variable, so you can use window.M.AutoInit()
, for instance.
So in the component where you use the modals, autoinit them in a useEffect callback:
useEffect(() => {
window.M.AutoInit();
}, []);