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

PureComponents might not be updated #944

Closed
theKashey opened this issue Apr 24, 2018 · 30 comments
Closed

PureComponents might not be updated #944

theKashey opened this issue Apr 24, 2018 · 30 comments
Assignees

Comments

@theKashey
Copy link
Collaborator

Original problem - I could not find any test related to PureComponents at all.

@theKashey theKashey self-assigned this Apr 24, 2018
theKashey added a commit that referenced this issue Apr 24, 2018
@theKashey
Copy link
Collaborator Author

Reported by @elisherer

It has something to do with me using react-waterfall which isn't doing anything wrong (from my perspective).
Check it out on: https://github.com/elisherer/react-hot-loader-repro918
I added examples of:

Class component
Function component
Pure Class component
Consumer Class component
Consumer Function component
Consumer Pure Class component
Children as a Function component
Consumer "Connected" component
Connected Children as a Function component
Component in a portal (modal)
All is working well besides the react-waterfall example.
react-waterfall is a mixture of the above and still manages to break, I added the library's source into the repo so you could fiddle with it.
I Couldn't get it to work.

Current state - could not create a red🛑 test to start with.

@gregberge
Copy link
Collaborator

Test added, I think the source of the problem is not PureComponent.

@theKashey
Copy link
Collaborator Author

@neoziro - changing PureComponent to Component in the original example does solve the problem in real.
The second thought was about using _children, thus "disabling" some heuristics, but I've tried the same it tests - always green.

The problem still exists and easily reproducible (in complex example)

@elisherer
Copy link

elisherer commented Apr 24, 2018

@theKashey, I managed to recreate the problem without react-waterfall (I removed it from my repo)

See:
https://github.com/elisherer/react-hot-loader-repro918/blob/master/src/components/FunctionConsumerPureClassComponent.js

@theKashey
Copy link
Collaborator Author

Pure Component just next to Context Consumer. Double kill! ☠︎
As long changing PureComponent to Component do the job, and we got control over PureComponent itself - solvable.

@theKashey theKashey reopened this Apr 24, 2018
@baldurh
Copy link

baldurh commented Apr 25, 2018

I’m using 4.0.1 and it works fine. Wanted to update to the latest version and ran into some issues with hot reloading. I have an example where I have nested PureComponents and changes aren’t being reloaded in a nested PureComponent. However, if I change it’s parent to Component it starts to work.

@theKashey
Copy link
Collaborator Author

Strange. I have almost the same situation in the tests - Pure inside Pure, and they works.

@baldurh
Copy link

baldurh commented Apr 25, 2018

For completeness:

<AsyncRouteComponent>
  <HotHOC>
    <PureComponent>
      <Fragment>
        <Component>
          <PureComponent>
            <PureComponent>
              <PureComponent>
                <PureComponent> // Change this one to Component and it starts working
                  <PureComponent>
                    <PureComponent /> // <- does not hot reload
                  </PureComponent>
                </PureComponent>
              </PureComponent>
            </PureComponent>
          </PureComponent>
        </Component>
      </Fragment>
    </PureComponent>
  </HotHOC>
</AsyncRouteComponent>

@theKashey
Copy link
Collaborator Author

:notsureif:

<AsyncRouteComponent>
  <HotHOC>
    <PureComponent>
      <Fragment>
        <Component>
          <PureComponent>// this works?
            <PureComponent>// this works?
              <PureComponent> // this works?
                <PureComponent> // Change this one to Component and it starts working (and "this works?")
                  <PureComponent> // this works?
                    <PureComponent /> // <- does not hot reload (BUT ONLY THIS!)
                  </PureComponent>
                </PureComponent>
              </PureComponent>
            </PureComponent>
          </PureComponent>
        </Component>
      </Fragment>
    </PureComponent>
  </HotHOC>
</AsyncRouteComponent>

@baldurh
Copy link

baldurh commented Apr 25, 2018

Yeah this wasn’t totally correct. Sorry.
It’s pretty much just stopping at that one component.
That Row component is Pure and the props that are passed to it do not change before and after hot reloading so it does not trigger a re-render. If I change one of the props to a new random value generated on each render it starts working again. So it seems the force update is broken.

<AsyncRouteComponent>
  <HotHOC>
    <PureComponent>
      <Fragment>
        <Component>
          <PureComponent> // this works? Yes
            <PureComponent> // this works? Yes
              <PureComponent> // this works? Yes
                <PureComponent_Row> // **Everything stops here** Change this one to Component and it starts working (and "this works?")
                  <PureComponent> // this works? No
                    <PureComponent /> // <- does not hot reload (BUT ONLY THIS!) No
                  </PureComponent>
                </PureComponent_Row>
              </PureComponent>
            </PureComponent>
          </PureComponent>
        </Component>
      </Fragment>
    </PureComponent>
  </HotHOC>
</AsyncRouteComponent>

@theKashey
Copy link
Collaborator Author

So, how PureComponent_Row is different? Why does everything stop on it?

@baldurh
Copy link

baldurh commented Apr 25, 2018

The only thing I can think of is that the props that are being passed into PureComponent_Row don’t change so it does not re-render on its own. Something needs to force it to re-render I guess.

@theKashey
Copy link
Collaborator Author

I've tracked down the problem. Fixing...

@theKashey
Copy link
Collaborator Author

@elisherer - going to add your repo to our examples. Be be able to test it in the future

@IMalyugin
Copy link

IMalyugin commented May 17, 2018

@theKashey , PureComponent does not get updated if it's located after the 16.3 Context.Provider, is this a known issue?

"react": "^16.3.2",
"react-dom": "16.3.2",
"react-hot-loader": "^4.2.0",

Here's the smallest configuration reproducing this:

import React from 'react';
import { hot } from 'react-hot-loader';

const Context = React.createContext();
class Component extends React.PureComponent {
  render() {
    return 'This Does not get updated';
  }
}

const App = () => (
  <div>
    <Context.Provider />
    <Component />
  </div>
);

export default hot(module)(App);

@theKashey
Copy link
Collaborator Author

That is should fixed in the latest release. 4.2.0 adds support for Context and should solve this task.

@IMalyugin
Copy link

@theKashey , as I mentioned, I am already using 4.2.0, just before updating from 4.1.2, context blocked updates in nested components, now they work well, but PureComponents stop updating if located after context block.

@theKashey
Copy link
Collaborator Author

Ok, I fixed the case, when PureComponent is located inside Context, but not next. actually it should not be a problem.
The only possible reason - Provider did throw an error. Where is value, I am actually counting on?

@IMalyugin
Copy link

No errors in console and in my app, I've got proper provider with value, consumer children while pure components are actually redux connected components.

I've just been reducing the structure required to reproduce this till I got down to the above.

Should add example as a test case for TDD and see for yourself :)

@theKashey
Copy link
Collaborator Author

Just set setConfig({logLevel: 'debug'}), then you will see an error.

@IMalyugin
Copy link

IMalyugin commented May 18, 2018

@theKashey , yes, with logLevel = 'debug' it throws value of undefined error, except it's not caused by no value passed to context, as it still fires even with this code. It's given default value, value, and even consumer.

import React from 'react';
import { hot, setConfig } from 'react-hot-loader';
setConfig({ logLevel: 'debug' });

const Context = React.createContext('default');
class Component extends React.PureComponent {
  render() {
    return 'This Does not get updated';
  }
}

const App = () => (
  <div>
    <Context.Provider value="test">
      <Context.Consumer>
        {val => val}
      </Context.Consumer>
    </Context.Provider>
    <Component />
  </div>
);

export default hot(module)(App);

@theKashey
Copy link
Collaborator Author

@IMalyugin - thanks for report. Fix will arrive soon.

@baldurh
Copy link

baldurh commented May 18, 2018

OK I tracked down my issue. This seems to have something to do with our use of lodash’s memoize function. When I do logLevel: 'debug'. I get the error: resolver is not defined after hot-reload. If I remove all calls to memoize it is fixed. See #984

@baldurh
Copy link

baldurh commented May 18, 2018

Actually, I believe the issue I reported earlier in this thread is fixed in 4.2.0 and #984 is a new one.

theKashey added a commit that referenced this issue May 22, 2018
fix: Context Provider could crash update, #944
@theKashey
Copy link
Collaborator Author

Everything should fixed in v4.3.0

@IMalyugin
Copy link

@theKashey Yep, it's all fixed now, thanks :)

@Verikon
Copy link

Verikon commented Jul 25, 2018

I've experienced something very similar when I'm using a React.Fragments. Everything hot reloads until the third or forth Fragment - then it halts. If unrelated I'll file another ticket but thought I'd first mention it here.

@theKashey
Copy link
Collaborator Author

Every time I announce: * Hey! At last it works! *, it doesn't :)

@Verikon
Copy link

Verikon commented Jul 30, 2018

@theKashey - I think you deserve a little more than some dribble that something looks like it may not work. I should be able to get you a much cleaner test case soon - or confirmation that I'm on drugs ;)

@theKashey
Copy link
Collaborator Author

Obliviously - React-Hot-Loader does not always work.
I have some examples as a proof - they are partially not working, and I don't know why.

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