isomorphic-style-loader icon indicating copy to clipboard operation
isomorphic-style-loader copied to clipboard

TypeError: Cannot read property 'apply' of undefined

Open pricetula opened this issue 7 years ago • 14 comments

Following instructions cannot get package to work I get the error below: TypeError: Cannot read property 'apply' of undefined at WithStyles.componentWillMount

import withStyles from 'isomorphic-style-loader/lib/withStyles';
import style from './style.js';

const App = () => <div>Test</div>;
export default withStyles(style)(App);

style.css

body
  background-color: #f00

postcss.config.js

module.exports = {
  parser: 'sugarss',
  plugins: {}
}

webpack.config.js

loaders: [
........
{
        test: /\.css$/,
        use: [
          'isomorphic-style-loader',
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1
            }
          },
          'postcss-loader',
        ]
      },
..........

Let me know how i can resolve this might be something wrong with my set up?

pricetula avatar Aug 31 '17 13:08 pricetula

I faced the same issue until I realized I missed the context in the parent react container.

ksankaran avatar Sep 06 '17 05:09 ksankaran

is it possible you could show me a repo for simple example....thanks @ksankaran

pricetula avatar Sep 06 '17 08:09 pricetula

I have a same problem. In react component:

`import withStyles from 'isomorphic-style-loader/lib/withStyles'; import s from './HelloWorldPage.sass';

...

return ( <div className={s.App}> <h1>Hello World!</h1> </div> ); .... export default withStyles(s)(App);`

And in server-side file: `... const css = new Set();

const context = { insertCss: (...styles) => styles.forEach(s => css.add(s.getCss())) }; ... const component = ( <StaticRouter location={req.url} context={context}> <App /> </StaticRouter> );`

I got TypeError:

TypeError: Cannot read property 'apply' of undefined at WithStyles.componentWillMount (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/isomorphic-style-loader/lib/withStyles.js:71:64) at /media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactCompositeComponent.js:345:23 at measureLifeCyclePerf (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactCompositeComponent.js:73:12) at ReactCompositeComponentWrapper.performInitialMount (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactCompositeComponent.js:344:9) at ReactCompositeComponentWrapper.mountComponent (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactCompositeComponent.js:255:21) at Object.mountComponent (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactReconciler.js:43:35) at ReactCompositeComponentWrapper.performInitialMount (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactCompositeComponent.js:368:34) at ReactCompositeComponentWrapper.mountComponent (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactCompositeComponent.js:255:21) at Object.mountComponent (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactReconciler.js:43:35) at ReactCompositeComponentWrapper.performInitialMount (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactCompositeComponent.js:368:34) at ReactCompositeComponentWrapper.mountComponent (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactCompositeComponent.js:255:21) at Object.mountComponent (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactReconciler.js:43:35) at ReactCompositeComponentWrapper.performInitialMount (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactCompositeComponent.js:368:34) at ReactCompositeComponentWrapper.mountComponent (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactCompositeComponent.js:255:21) at Object.mountComponent (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactReconciler.js:43:35) at ReactDOMComponent.mountChildren (/media/ruut/MyDisk/Soft/Programming/MyProjects/JS/dpk/node_modules/react-dom/lib/ReactMultiChild.js:234:44)

How I can to resolve this problem? Who will can help me? Plz.

ChugunovRoman avatar Oct 21 '17 14:10 ChugunovRoman

The problem is solving by add your own <ContextProvider> component. <StaticRouter> not passing insertCss to child node. For example:

class ContextProvider extends React.Component {
  static childContextTypes = {
    insertCss: PropTypes.func,
  }
  
  getChildContext() {
    return { ...this.props.context }
  }
  
  render () {
    return <App { ...this.props } />
  }
}

and wrap your <App> like this:

<StaticRouter location={req.url} context={context}>
  <ContextProvider context={context}>
    <App />
  </ContextProvider>
</StaticRouter>

Don't forget to add context: { insertCss: ... } to client part:

const context = {
  insertCss: (...styles) => {
    const removeCss = styles.map(x => x._insertCss());
    return () => {
      removeCss.forEach(f => f());
    };
  },
}

Vusluk avatar Oct 25 '17 06:10 Vusluk

hey @Vusluk , I don't understand from where this line return <App { ...this.props } /> came.

Could you explain?

dleitee avatar Oct 25 '17 11:10 dleitee

I think it is better:

render() {
    const { children, ...props } = this.props
    return React.cloneElement(children, props)
  }

dleitee avatar Oct 25 '17 11:10 dleitee

@dleitee Yes, you are right, this is mistake. I'm just copy/paste and did not notice. Thanks. But why you suggest cloneElement(...) instead of createElement(...)?

Vusluk avatar Oct 25 '17 11:10 Vusluk

@Vusluk because with the cloneElement(...) all props of children will be copied and with the createElement(...) don't.

dleitee avatar Oct 25 '17 23:10 dleitee

Hi @Vusluk, @dleitee I have add this code at client side(index.js): in render() function const context = { insertCss: (...styles) => { console.log('styles',styles); const removeCss = styles.map(x => x._insertCss()); return () => { removeCss.forEach(f => f()); }; }, }; return ( <Router history={browserHistory}> <ContextProvider context={context}> {routes()} </ContextProvider> </Router> ); it is displaying as in broswer console "x._insertCss is not a function"

below solution is worked for me: render() { const context = { insertCss(...styles) { styles.forEach(style => style._insertCss()); }, }; return ( <Router history={browserHistory}> <ContextProvider context={context}> {routes()} </ContextProvider> </Router> ); }

NithishReddy avatar Jan 29 '18 09:01 NithishReddy

is there any way to load entire page css in parent component and accessed in child components or we have to explicitly import css in child components also?

NithishReddy avatar Jan 29 '18 11:01 NithishReddy

@NithishReddy Hi! It was difficult to read your code without formatting. It's bad idea to create context inside render() because it will create new insertCss function every virtual DOM rerender. This is my working code:

import React from 'react'
import { hydrate } from 'react-dom'
import { ConnectedRouter } from 'react-router-redux'
import { Provider } from 'react-redux'
import { browserHistory, BrowserRouter, Redirect, IndexRedirect, Route } from 'react-router'
import { AppContainer } from 'react-hot-loader'

import store from './store'
import history from './history'

import App from './App/container.jsx'

const container = document.getElementById('root')

const context = {
  insertCss: (...styles) => {
    const removeCss = styles.map(x => x._insertCss());
    return () => {
      removeCss.forEach(f => f());
    };
  },
}

const render = Root => hydrate(
  <AppContainer key={Math.random()}>
    <Provider store={store}>
      <ConnectedRouter history={history}>
        <Root context={context} />
      </ConnectedRouter>
    </Provider>
  </AppContainer>,
  container
)

render(App)

if (module.hot) module.hot.accept('./App/container.jsx', () => render(require('./App/container').default))

App is root component and performs ContextProvider function and all other system/architecture functionality.

Vusluk avatar Feb 02 '18 16:02 Vusluk

Thanks. what is the exact use of ContextProvider and some explaination on it?(am implementing universal app like sever-side and client-side rendering).

On Fri, Feb 2, 2018 at 10:06 PM, Stanislav Dubrovsky < [email protected]> wrote:

@NithishReddy https://github.com/nithishreddy Hi! It was difficult to read your code without formatting. It's bad idea to create context inside render() because it will create new insertCss function every virtual DOM rerender. This is my working code:

import React from 'react' import { hydrate } from 'react-dom' import { ConnectedRouter } from 'react-router-redux' import { Provider } from 'react-redux' import { browserHistory, BrowserRouter, Redirect, IndexRedirect, Route } from 'react-router' import { AppContainer } from 'react-hot-loader'

import store from './store' import history from './history'

import App from './App/container.jsx'

const container = document.getElementById('root')

const context = { insertCss: (...styles) => { const removeCss = styles.map(x => x._insertCss()); return () => { removeCss.forEach(f => f()); }; }, }

const render = Root => hydrate( <AppContainer key={Math.random()}> <Provider store={store}> <ConnectedRouter history={history}> <Root context={context} /> </ConnectedRouter> </Provider> </AppContainer>, container )

render(App)

if (module.hot) module.hot.accept('./App/container.jsx', () => render(require('./App/container').default))

App is root component and performs ContextProvider function and all other system/architecture functionality.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/kriasoft/isomorphic-style-loader/issues/110#issuecomment-362627970, or mute the thread https://github.com/notifications/unsubscribe-auth/AMkql-u1eDuDE8Ia78tzhnf5uuXGV_wTks5tQzJ2gaJpZM4PIzuD .

NithishReddy avatar Feb 03 '18 08:02 NithishReddy

does it support https://reactjs.org/docs/context.html#reactcreatecontext ?

antonybudianto avatar Jun 22 '18 06:06 antonybudianto

The same error! webpack.config

{
    test: /\.scss$/,
    use: [
        'isomorphic-style-loader',
        'css-loader?modules',
        'sass-loader'
    ]
}

test.scss

.test{
    font-size: 24px;
    /*color: red;*/
}

Todos.js

import style from 'scss/test/scss';
console.log(style);
//{test: "_3GxNmfH38vHbRin87tUbfa", _getContent: ƒ, _getCss: ƒ, _insertCss: ƒ}

@connect(state => ({
    todo: state.todo
}))
class Todos extends React.Component {

    async componentDidMount () {
        const { todo = {}, dispatch } = this.props;
        const { todoList } = todo;
        if (todoList.length <= 0) {
            dispatch(getTodoList());
        }
    }

    render () {
        const { todo } = this.props;
        const { todoList } = todo;
        return <ul className={style.test}>{todoList.map(todo => <li key={todo.id}>{todo.title}</li>)}</ul>;
    }
}

export default (Todos);

If I not use the withStyles class _3GxNmfH38vHbRin87tUbfa was added to the ul element, but the style font-size:24px; is not working . If using withStyles the error is shown.

Uncaught TypeError: Cannot read property 'apply' of undefined
The above error occurred in the <WithStyles(Connect(Todos))> component:

This error on the client environment

I called style._insertCss(); that work on the client.

Can I use like this?

mqliutie avatar Aug 28 '18 09:08 mqliutie