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

Unneeded renders in withInitAction when INIT_COMPONENT fires #24

Closed
ThaNarie opened this issue Nov 2, 2017 · 1 comment
Closed

Unneeded renders in withInitAction when INIT_COMPONENT fires #24

ThaNarie opened this issue Nov 2, 2017 · 1 comment

Comments

@ThaNarie
Copy link
Member

ThaNarie commented Nov 2, 2017

It looks like every INIT_COMPONENT causes all withInitAction's connect to execute and cause re-renders.

I'm not 100% sure, but it looks like the following is happening:

  1. When INIT_COMPONENT fires from any component, the selfInit in the reducer is updated where completed is updated for the prepareHash for that component:

    selfInit: {
    ...state.selfInit,
    [action.payload.prepareKey]: action.payload.complete,
    },

  2. When that happens, the 2nd param in the selector will 'break' the memoization:

    state => state.selfInit,

  3. This will cause the connect in withInitAction to return a new object for __componentInitState:

    const __componentInitState = componentInitStateSelector(initState, ownProps);
    return {
    __componentInitState,
    __modeInitSelf: initState.mode === MODE_INIT_SELF,
    };

  4. Because of 3), the withInitAction component will cause a re-render itself.

  5. Most of the time when withInitAction is used to get some data, the same component is also wrapped into a connect to get the info from the state. The connect will not 'block' the re-render of the wrapped component, since it will only do purity checks on the output of it's own mapStateToProps.

  6. And because of 4) The wrapped component will also be re-rendered. In this case, making it a PureComponent will halt the re-render, because the render in 4) didn't pass any new/updated props.

Possible fix;

  1. improve the selector from 2) to better deal with state updates that are not relevant for that component, or
  2. add a custom equality check for the withInitAction connect to battle the failing selector, or
  3. implement a shouldComponentUpdate in the withInitAction component as a last resort.

Example:
If we have a tree of 50 components that have a withInitAction, and all of them will start and complete (two actions per component), all 50 components will re-render on all of the 100 actions, causing a lot of usless code execution.

@flut1
Copy link
Contributor

flut1 commented Nov 3, 2017

Thanks for the thorough investigation 👍 We should definitely fix the selector memoization, because that's the whole point of using a selector.

@flut1 flut1 mentioned this issue Nov 3, 2017
@flut1 flut1 closed this as completed Nov 3, 2017
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

2 participants