Inferno: Inferno 1.6.1: Wrong error message for setState & maybe a breaking change.

Created on 5 Apr 2017  路  16Comments  路  Source: infernojs/inferno

I updated inferno to 1.6.1 and I got this error:

Inferno Error: cannot update state via setState() in componentWillUpdate() or constructor.

I didn't use setState on those but in componentWillMount. The message is not correct and confusing.
Additionally I think this change broke the possibility of setting up the state for server side rendering:

https://github.com/infernojs/inferno/commit/39d5922eb7e5e2a9093e505c72170b572200f9cd

If _blockSetState = true; by default then I can't setup the state before to render. In the client side no problems because I can use componentDidMount (btw componentDidMount only runs in the client side).

Unless I am completely confused. How/Where I can setup the state before to render for SSR? cc @trueadm @Havunen

Thanks a lot for your help guys. We are rebuilding the redbull.tv site using inferno and we can't be happier. The bundles are smaller and the site feels way faster for mobile and desktop.

bug

All 16 comments

The error message is confusing. Typically though, you shouldn't be using componentWillMount to setState as it will be async. You should be assigning the state in the constructor instead. If state is something you need to compute/work out, you can probably do this in the constructor as long as it's sync and not async (server-side rendering with renderToString isn't async).

Personally, I feel server-side rendering should ideally have it's own lifecycle event, or we should disable this error from occurring during server-side rendering though.

@trueadm Yes, I did set the state in componentWillMount because I have my own Provider to pass the data to the components in the SSR process. In the components I use this.context to access to the data. Unfortunately the this.context is null in the constructor but later it is available which I don't know if it is a bug or an expected behavior.,
By the way I tried using setState in the constructor but I am getting the same error: Inferno Error: cannot update state via setState() in componentWillUpdate() or constructor. Maybe we need to revert this commit https://github.com/infernojs/inferno/commit/39d5922eb7e5e2a9093e505c72170b572200f9cd until we find a better way to control the setState or your new lifecycle proposal for SSR?
SSR is extremely important for many people and maybe we need to rethink it....and for now revert?
cc @Havunen

@hguillermo context is passed in as the 2nd argument to your constructor. We should probably define it too beforehand though in the base component. Rather than revert that commit, I'd rather _blockSetState get set to false after the constructor has been executed.

In fact, this is already the case it appears:

https://github.com/infernojs/inferno/blob/master/packages/inferno/src/DOM/utils.ts#L34

I'm confused as to how this error is being thrown if that flag is being set to false.

Yeah it sounds like bug or something really strange is happening there, also all our tests pass :/

@hguillermo could you debug and check why its giving that error as the flag should be set false immediately after constructor call?

@Havunen @trueadm Ok. I will create a jsfiddle or so soon. Thanks again for all your support guys.

@trueadm @Havunen Check this fiddle: https://jsfiddle.net/zy4fof9m/6/

You will see that the code does work but if you replace:

this.state = {
  progress: 0
};

By

this.setState = ({
  progress: 0
});

it won't work.

@hguillermo you can't and never should do setState in the constructor, ever, that's why!

@trueadm I see! I got confused because I read this: Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.. From this link https://facebook.github.io/react/docs/react-component.html#setstate (at the end). Is that not the case for inferno? Maybe the react documentation is not good?
I am okay if we can use this.state = whatever in the constructor if you think it is acceptable.
Thanks again for all your help and time. You guys are doing an amazing job!

Okay documentation should be improved, you need to initialize state object in constructor but not call setState. Happy that you got your issue resolved

Thank you @Havunen! I guess the only pending thing is the message:

Inferno Error: cannot update state via setState() in componentWillUpdate() or constructor.

I got that message when I had setState in componentWillMount(). Maybe we can just update the error message? I suppose after that we can close this issue if you think it is worth it to modify the message.

Also I remember you were going to include a section in the web site for companies using inferno? I will be happy to add RedBullTV in that list. Let me know. Thanks again!

"I got that message when I had setState in componentWillMount().". It should be allowed to update state on componentWillMount can you share code that causes this exception

This is bug, I have reproduced it now.

ok. I will debug it and try to put a PR.

nvm. It is fixed! Thanks a lot. I am going to close this issue. Thanks @Havunen!!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

trueadm picture trueadm  路  25Comments

kanzelm3 picture kanzelm3  路  35Comments

darsain picture darsain  路  47Comments

davedbase picture davedbase  路  47Comments

fmarsoni picture fmarsoni  路  25Comments