kriasoft / isomorphic-style-loader

CSS style loader for Webpack that is optimized for isomorphic (universal) web apps.
https://reactstarter.com
MIT License
1.27k stars 144 forks source link

TypeError: Cannot read property 'apply' of undefined #110

Open pricetula opened 7 years ago

pricetula commented 7 years ago

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?

ksankaran commented 7 years ago

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

pricetula commented 7 years ago

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

ChugunovRoman commented 6 years ago

I have a same problem. In react component:

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

...

return ( \

\

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 = ( \ \<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.

Vusluk commented 6 years ago

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());
    };
  },
}
dleitee commented 6 years ago

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

Could you explain?

dleitee commented 6 years ago

I think it is better:

render() {
    const { children, ...props } = this.props
    return React.cloneElement(children, props)
  }
Vusluk commented 6 years ago

@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(...)?

dleitee commented 6 years ago

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

NithishReddy commented 6 years ago

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 (

{routes()}
        );

` 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 (

{routes()}
        );
}`
NithishReddy commented 6 years ago

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?

Vusluk commented 6 years ago

@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.

NithishReddy commented 6 years ago

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 < notifications@github.com> 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(

, 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 , or mute the thread .
antonybudianto commented 6 years ago
mqliutie commented 6 years ago

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?