Skip to content Skip to sidebar Skip to footer

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:

  1. Create a ContextProvider component in the same directory of App

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
  1. Wrap the ContextProvider in BOTH your browser.js and server.js. Remember to declare the context 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"