Preact: Scroll position is not persistent when changing state in context.

Created on 2 Feb 2020  路  7Comments  路  Source: preactjs/preact

Hey!

I'm having an issue with a nonpersistent scroll position when using useState hook in Context in Gatsby project (same when I use this.setState). It scrolls to the top after each call.

Demos:

  1. React (everything works as expected) - preview / video / repo (branch master)
  2. Preact - preview / video / repo (branch with-preact)

The only difference between those 2 is in using gatsby-plugin-preact which changes React to Preact during the production build.

compat help wanted

Most helpful comment

Confirmed! Just updated Preact and 10.4.0 has fixed this issue! 馃帀
Thank you, guys!

All 7 comments

Hey,

I've tried this out with a barebones Preact project and this doesn't seem to be the case: https://codesandbox.io/s/unruffled-forest-81880

We might have to look into some gatsby specifics or the router you're using.

Gatsby is resetting scroll position in a componentDidUpdate callback on their root component:
https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-react-router-scroll/src/ScrollBehaviorContext.js#L58

For whatever reason, React does not end up invoking componentDidUpdate when clicking the button. That makes this a potential compat bug, though I haven't ruled out Gatsby doing something odd here.

I did some digging and it seems like context diffing is different between React & Preact.

Here is an example where React & Preact are both in the same app. The first one is React and the second one is Preact.
https://codesandbox.io/s/react-preact-childcontext-bug-9l51h

In React when I hit the button in React, this is the render log:

REACT: Render CounterContextProvider 
REACT: Render Counter 
REACT: Render Value

For Preact this is the render log:

PREACT: Render CounterContextProvider 
PREACT: Render ParentComponent 
PREACT: Render Counter 
PREACT: Render Value 

I can fix this behavior by adding shouldComponentUpdate to the ParentComponent. In React shouldComponentUpdate isn't even called for the ParentComponent

  shouldComponentUpdate(nextProps, nextState, nextContext) {
    return (
      this.props !== nextProps &&
      this.state !== nextState &&
      this.context !== nextContext
    );
  }

I'm happy to fix this myself if I can get some pointers but the diff code is a bit overwhelming 馃槢

Hey @developit @JoviDeCroock, what should be the next step in your opinion? Looks like it's related to Preact, not Gatsby?

@thomkrupa have you tested the latest preact version? It should fix this issue.

I'm very sorry, I forgot to come back to this and mention it in my PR. This has been released in 10.4.0.

The gist of it is that we can skip the update of ParentComponent because of an optimization better explained here this is used in React and a lot of libraries rely on it.

Confirmed! Just updated Preact and 10.4.0 has fixed this issue! 馃帀
Thank you, guys!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

marcosguti picture marcosguti  路  3Comments

matuscongrady picture matuscongrady  路  3Comments

matthewmueller picture matthewmueller  路  3Comments

KnisterPeter picture KnisterPeter  路  3Comments

SabirAmeen picture SabirAmeen  路  3Comments