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

no match between SSR'ed Dom structure and rehydrated #65

Open
khanbaba opened this issue Aug 31, 2020 · 19 comments
Open

no match between SSR'ed Dom structure and rehydrated #65

khanbaba opened this issue Aug 31, 2020 · 19 comments
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@khanbaba
Copy link

khanbaba commented Aug 31, 2020

here is code of my page:

render() {
    const {
      query: { random_key }
    } = this.props
    return (
      <KeepAlive id={random_key} name={`p/${random_key}`}>
        <ScrollPosition>
          <Product {...this.props} />
        </ScrollPosition>
      </KeepAlive>
    )
  }

Rehydrated page must matches the original SSR'ed page otherwise react will recreate DOM and as a side effect core web vitals metrics like LCP will be measured after client-side rehydration.

@khanbaba
Copy link
Author

this is console error of this problem:
rehydration-problem

implementation environment:
reactjs: 16.13.1
nextjs: 9.4.4
react-activation: 0.4.2

@khanbaba
Copy link
Author

khanbaba commented Sep 2, 2020

I also checked react-activation version 0.5.5 and the problem exists.

@CJY0208
Copy link
Owner

CJY0208 commented Sep 2, 2020

I have almost no experience with React SSR hydrate, so I just made a simple SSR compatibility in react-activation

The implementation of react-activation determines that it may not be able to guarantee that the content rendered by the client and server is consistent when the application is initialized.

Do you have any idea on this issue?

@CJY0208 CJY0208 added help wanted Extra attention is needed bug Something isn't working labels Sep 2, 2020
@khanbaba
Copy link
Author

khanbaba commented Sep 2, 2020

please read this post: https://joshwcomeau.com/react/the-perils-of-rehydration/
you should remove some stochastic conditions in the code.

@khanbaba
Copy link
Author

khanbaba commented Sep 5, 2020

same issue on react-keep-alive: StructureBuilder/react-keep-alive#85

@khanbaba
Copy link
Author

Hi @CJY0208, can you please explain briefly how you added SSR to react-keep-alive library. I have to fix this issue if you write some help about the implementation.

@AlexSapoznikov
Copy link

I confirm this is an issue, still forced to use react-keep-alive due to this issue.

@khanbaba
Copy link
Author

I confirm this is an issue, still forced to use react-keep-alive due to this issue.

Hi @AlexSapoznikov I have decided to not use react-keep-alive and i have used another better solution to keep my pages alive in react.

@AlexSapoznikov
Copy link

I confirm this is an issue, still forced to use react-keep-alive due to this issue.

Hi @AlexSapoznikov I have decided to not use react-keep-alive and i have used another better solution to keep my pages alive in react.

Hi @khanbaba
So what are you using, if I may ask?

@khanbaba
Copy link
Author

I confirm this is an issue, still forced to use react-keep-alive due to this issue.

Hi @AlexSapoznikov I have decided to not use react-keep-alive and i have used another better solution to keep my pages alive in react.

Hi @khanbaba
So what are you using, if I may ask?

read the solution here: https://stackoverflow.com/questions/59124463/nextjs-how-to-not-unmount-previous-page-when-going-to-next-page-to-keep-state

@AlexSapoznikov
Copy link

I confirm this is an issue, still forced to use react-keep-alive due to this issue.

Hi @AlexSapoznikov I have decided to not use react-keep-alive and i have used another better solution to keep my pages alive in react.

Hi @khanbaba
So what are you using, if I may ask?

read the solution here: https://stackoverflow.com/questions/59124463/nextjs-how-to-not-unmount-previous-page-when-going-to-next-page-to-keep-state

Thanks! Will look into it.

@luhc228
Copy link

luhc228 commented Sep 22, 2022

有进展吗? @CJY0208

@luhc228
Copy link

luhc228 commented Sep 23, 2022

@CJY0208 cc

出问题应该是这里,在 server 端和 client 端分别使用了不同的组件进行渲染,导致了出现节点匹配不一致的问题。 其实这里不需要环境的判断,直接使用 expandKeepAlive(withActivation(KeepAlive)) 在双端渲染也是 ok 的

export default isFunction(get(root, 'document.getElementById'))

我 debug 到这里的时候大概发现的是,react 在进行 hydrate 的时候,就出来了节点 mismatch 的情况了

image

复现路径:
可以在 feat/keep-alive-plugin 这个分支上,执行 npm run setup 脚本安装依赖后,然后 cd example/with-keep-alive 执行 npm start 即可复现问题了

参考:facebook/react#24384

@CJY0208
Copy link
Owner

CJY0208 commented Sep 23, 2022

意思就是 keep alive 组件的 ssr 和 csr 逻辑不一致所以报错了

但现在面临一个问题,keep alive 的原理本来就是先渲染到别处再 dom 移回来的

ssr 没有 dom 所以是直接渲染的

如果要 ssr 也和 csr 保持一致,那可能导致 ssr 的产物里,KeepAlive 内部的视图显示不出来

@luhc228
Copy link

luhc228 commented Sep 23, 2022

意思就是 keep alive 组件的 ssr 和 csr 逻辑不一致所以报错了

但现在面临一个问题,keep alive 的原理本来就是先渲染到别处再 dom 移回来的

ssr 没有 dom 所以是直接渲染的

如果要 ssr 也和 csr 保持一致,那可能导致 ssr 的产物里,KeepAlive 内部的视图显示不出来

ssr 只关心第一次渲染的结果,后面视图更新都是由 csr 承接的。你现在只需要保证 ssr KeepAlive 内的内容出来就行,事实上是可以的。

@CJY0208
Copy link
Owner

CJY0208 commented Sep 23, 2022

现在可见的修复措施,产生的结果可能是 ssr 首屏的内容里,KeepAlive 标签包裹的部分会是空白的,这个感觉是不可接受的吧

@luhc228
Copy link

luhc228 commented Sep 23, 2022

现在可见的修复措施,产生的结果可能是 ssr 首屏的内容里,KeepAlive 标签包裹的部分会是空白的,这个感觉是不可接受的吧

什么情况下是空白的?目前我用的时候没有空白

@nfrederick023
Copy link

Not a great solution, but if you're willing to sacrifice an extra re-render here's a hack for NextJS.

Create a KeepAlive wrapper component:

import { KeepAlive as _KeepAlive } from "react-activation";
import React, { FC, ReactNode, useEffect, useState } from "react";

export interface KeepAliveProps {
  children: ReactNode;
}

const KeepAlive: FC<KeepAliveProps> = ({ children }: KeepAliveProps) => {
  const [keepAliveChildren, setKeepAliveChildren] = useState(<>{children}</>);

  useEffect(() => {
    setKeepAliveChildren(<_KeepAlive saveScrollPosition="screen">{children}</_KeepAlive>);
  }, []);

  return <>{keepAliveChildren}</>;
};

export default KeepAlive;

and then use it like this:

import KeepAlive from "@client/components/common/shared/keep-alive";
import React, { FC } from "react";

const IndexPage: FC = () => {
  return (
    <KeepAlive>
      <div>Hello World!</div>
    </KeepAlive>
  );
};

export default IndexPage;

@chenweigh
Copy link

Not a great solution, but if you're willing to sacrifice an extra re-render here's a hack for NextJS.

Create a KeepAlive wrapper component:

import { KeepAlive as _KeepAlive } from "react-activation";
import React, { FC, ReactNode, useEffect, useState } from "react";

export interface KeepAliveProps {
  children: ReactNode;
}

const KeepAlive: FC<KeepAliveProps> = ({ children }: KeepAliveProps) => {
  const [keepAliveChildren, setKeepAliveChildren] = useState(<>{children}</>);

  useEffect(() => {
    setKeepAliveChildren(<_KeepAlive saveScrollPosition="screen">{children}</_KeepAlive>);
  }, []);

  return <>{keepAliveChildren}</>;
};

export default KeepAlive;

and then use it like this:

import KeepAlive from "@client/components/common/shared/keep-alive";
import React, { FC } from "react";

const IndexPage: FC = () => {
  return (
    <KeepAlive>
      <div>Hello World!</div>
    </KeepAlive>
  );
};

export default IndexPage;

The new Problem.

app-index.js:32 Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to `this.state` directly or define a `state = {};` class property with the desired state in the ProviderBridge component.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

6 participants