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
importReactfrom'react';
importPropTypesfrom'prop-types'importAppfrom'./App'classContextProviderextendsReact.Component {
static childContextTypes = {
insertCss: PropTypes.func,
}
getChildContext() {
return { ...this.props.context }
}
render () {
return<App { ...this.props } />
}
}
exportdefaultContextProvider
- 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
<ContextProvidercontext={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(
<StaticRouterlocation={req.url}><ContextProvidercontext={context}><App /></ContextProvider></StaticRouter>
)
res.send(`
<!DOCTYPE html><html><head><title>React on the Server!</title><scriptsrc="/bundle.js"defer></script><script>window.__INITIAL_DATA__ = ${serialize(data)}</script><styletype="text/css">${[...css].join('')}</style></head><body><divid="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"