Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error on re-render #484

Closed
PolGuixe opened this issue Sep 23, 2016 · 8 comments
Closed

Error on re-render #484

PolGuixe opened this issue Sep 23, 2016 · 8 comments

Comments

@PolGuixe
Copy link

The first time it loads its fine, however when I make a change and it tries to re-render shows this error message:

Cannot read property 'prepareStyles' of undefined
TypeError: Cannot read property 'prepareStyles' of undefined
    at RaisedButton.render (webpack:///~/material-ui/RaisedButton/RaisedButton.js:273:48)
    at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (webpack:///~/react/lib/ReactCompositeComponent.js:808:34)
    at ReactCompositeComponentWrapper._renderValidatedComponent (webpack:///~/react/lib/ReactCompositeComponent.js:835:34)
    at ReactCompositeComponentWrapper.performInitialMount (webpack:///~/react/lib/ReactCompositeComponent.js:372:30)
    at ReactCompositeComponentWrapper.mountComponent (webpack:///~/react/lib/ReactCompositeComponent.js:260:21)
    at Object.mountComponent (webpack:///~/react/lib/ReactReconciler.js:47:35)
    at ReactDOMComponent.mountChildren (webpack:///~/react/lib/ReactMultiChild.js:240:44)
    at ReactDOMComponent._createInitialChildren (webpack:///~/react/lib/ReactDOMComponent.js:698:32)
    at ReactDOMComponent.mountComponent (webpack:///~/react/lib/ReactDOMComponent.js:523:12)
    at Object.mountComponent (webpack:///~/react/lib/ReactReconciler.js:47:35)

Here is the code of the component:

import React from 'react';
import DropZone from 'react-dropzone';
import {RaisedButton, FontIcon} from 'material-ui';

class FileUploader extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        const {imageFiles} = this.props;
        return (
            <div>
                <DropZone className="drop-zone">
                    <RaisedButton label="Upload Pictures" icon={<FontIcon className="fa fa-upload"/>}/>
                    <p>
                        <small> here the product pictures in
                            <code>jpeg</code>
                             or
                            <code>png</code>
                            format, with size less or equal to 2MB</small>
                    </p>
                </DropZone>
                <div className="image-preview">
                    {imageFiles && imageFiles[0]
                        ? imageFiles.map((image) => {
                            return (
                                <div className="image-wrapper"><img src={image.preview
                                    ? image.preview
                                    : image.link()}/></div>
                            );
                        })
                        : <div>
                            <i className="fa fa-camera"></i>{' Preview Images'}</div>}
                </div>
            </div>
        );
    }
}

export default FileUploader;

I am also using a decorator to provide the props to the Material-UI components.

@usulpro
Copy link
Member

usulpro commented Sep 24, 2016

Cannot read property 'prepareStyles' of undefined

You have this error when you don't wrap material-ui components in MuiThemeProvider. So it's not a storybook issue.
You can use this addon to insert your component directly to storybook

@arunoda
Copy link
Member

arunoda commented Sep 25, 2016

Thanks @usulpro
Closing this since we've a good solution.

@arunoda arunoda closed this as completed Sep 25, 2016
@PolGuixe
Copy link
Author

@usulpro thanks for the addon. Looks great.

Just to know what I am doing wrong -so I can learn from it-, I got this error even when providing a theme using MuiThemeProvider. In my case I was using a decorator like:

import {configure, addDecorator} from '@kadira/storybook';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import '../client/theme/flexboxgrid.css';
import '../client/theme/new_theme.css';

// -----------------------------------------------------------
// TODO: remove when not necessary - dependency for Material-ui
import injectTapEventPlugin from 'react-tap-event-plugin';

// Needed for onTouchTap http://stackoverflow.com/a/34015469/988941
injectTapEventPlugin();
// -----------------------------------------------------------

const muiThemeDecorator = (story) => (
    <MuiThemeProvider>
        <div className="row around-xs">
            {story()}
        </div>
    </MuiThemeProvider>
);

addDecorator(muiThemeDecorator);

function loadStories() {
    require('../.stories');
    require('../client/modules/core/components/.stories');
    // require('../client/modules/products/components/.stories');
}

configure(loadStories, module);

The first time it renders fine, however on a change I get the error message above.

@usulpro
Copy link
Member

usulpro commented Sep 28, 2016

In general this code works well for me.
(just don't miss import React from 'react';)
Could you give more details where it goes wrong?

@CGamesPlay
Copy link

I have this same problem. When MuiThemeProvider is used from a decorator, hot reloading fails. Here is a repository which demonstrates: https://github.com/CGamesPlay/storybook-484

@keabard
Copy link

keabard commented Aug 7, 2017

Same problem here, testing my components wrapping material-ui own components, with Storybook and Specifications add-on.

Used addDecorator in my config.js file :

import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
addDecorator(story => (
  <MuiThemeProvider muiTheme={getMuiTheme()}>
    {story()}
  </MuiThemeProvider>
));

When I do a hard reload, everything works fine, but everytime there is a hot-reload, I get a "Cannot read property 'prepareStyles' of undefined".

EDIT : Found solution in another ticket : #463

@CGamesPlay
Copy link

Note that my test case repository does not include injectTapEventPlugin nor does the stack trace include that method.

@nathanredblur
Copy link

I notice that when 'storybook-addon-apollo-client' is active, my component do two renders, and if I activate 'storybook-react-i18next' my component do 4 unnecessary renders.

That is a problem, because I'm using MockedProvider and when a component do more renders than I'm expecting, my query is executed more than once, so I need to duplicate fake query mocks for each render.

on refresh the whole page, I don't have this issue. but when I do a change in the code, 4 to 6 unnecessary renders appears.

component

import WORLD_QUERY from './worldQuery.graphql';

const Hello = () => {
  const world = useQuery(WORLD_QUERY)
  return <div>{world}</div>
}

story

import WORLD_QUERY from './worldQuery.graphql';
const apolloMock = {
    request: { query: WORLD_QUERY },
    result: {
      data: "world",
    }
}

const Template = (args) => <Component {...args} />;

export const Default = Template.bind({});
Default.parameters = {
  apolloClient: {
    mocks: [
       // one request for each render generated 
       // on use 'storybook-addon-apollo-client' and 'storybook-react-i18next' addons
       apolloMock,
       apolloMock,
       apolloMock,
       apolloMock,
    ],
  },
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants