Why Does Isomorphic-style-loader Throw A TypeError: Cannot Read Property 'apply' Of Undefined When Being Used In Unison With CSS-Modules
I'm currently trying to render the application on the server, which works for the HTML and JS, but found that my styles (.less | .scss) would not load. I did some research and figu
Solution 1:
The problem went away simply because you removed isomorphic-style-loader
. Please don't accept your own answer like that. The problem here is you did not provide a context
so insertCss.apply(_context, styles)
will complain because _context
is undefined
. To solve the problem, follow these steps:
- Create a
ContextProvider
component in the same directory ofApp
ContextProvider.js
import React from 'react';
import PropTypes from 'prop-types'
import App from './App'
class ContextProvider extends React.Component {
static childContextTypes = {
insertCss: PropTypes.func,
}
getChildContext() {
return { ...this.props.context }
}
render () {
return <App { ...this.props } />
}
}
export default ContextProvider
- Wrap the
ContextProvider
in BOTH yourbrowser.js
andserver.js
. Remember to declare thecontext
in both files.
browser.js (in other apps, this would be root client code, i.e client.js
or index.js
)
// Import the neccessary modules for use in file
/* import statements */
const context = {
insertCss: (...styles) => {
const removeCss = styles.map(x => x._insertCss());
return () => {
removeCss.forEach(f => f());
};
},
}
hydrate(
<BrowserRouter>
//ContextProvider wraps around and returns App so we can do this
<ContextProvider context={context} />
</BrowserRouter>,
document.getElementById('app')
)
server.js
//Additional code above
app.get("*", (req, res, next) => {
const activeRoute = routes.find((route) => matchPath(req.url, route)) || {}
const promise = activeRoute.fetchInitialData
? activeRoute.fetchInitialData(req.path)
: Promise.resolve()
promise.then((data) => {
const css = new Set()
const context = { insertCss: (...styles) =>
styles.forEach(style => css.add(style._getCss()))}
const markup = renderToString(
<StaticRouter location={req.url}>
<ContextProvider context={context}>
<App />
</ContextProvider>
</StaticRouter>
)
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>React on the Server!</title>
<script src="/bundle.js" defer></script>
<script>window.__INITIAL_DATA__ = ${serialize(data)}</script>
<style type="text/css">${[...css].join('')}</style>
</head>
<body>
<div id="app">${markup}</div>
</body>
</html>
`)
}).catch(next)
})
app.listen(port, () => console.log(`Server is listening on port: ${port}`))
I wrote an article explaining this in more detail here: https://medium.com/@danielnmai/load-css-in-react-server-side-rendering-with-isomorphic-style-loader-848c8140a096
Post a Comment for "Why Does Isomorphic-style-loader Throw A TypeError: Cannot Read Property 'apply' Of Undefined When Being Used In Unison With CSS-Modules"