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

SSR: Cannot set property 'memoizedState' of null #16416

Open
ambar opened this issue Aug 16, 2019 · 26 comments
Open

SSR: Cannot set property 'memoizedState' of null #16416

ambar opened this issue Aug 16, 2019 · 26 comments

Comments

@ambar
Copy link

ambar commented Aug 16, 2019

Do you want to request a feature or report a bug?

A bug?

What is the current behavior?

Cannot set property 'memoizedState' of null

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:

const processLink = html => {
  return renderToStaticMarkup(<Link />)
};

const RichText = ({ html }) => {
  const htmlProcessed = useMemo(() => processLink(html), [html]);
}

See https://codesandbox.io/s/cannot-set-property-memoizedstate-of-null-mrxfr

What is the expected behavior?

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

16.8~16.9

@dhrubesh
Copy link

dhrubesh commented Oct 7, 2019

@bvaughn Mind if I take this up?

@bvaughn
Copy link
Collaborator

bvaughn commented Oct 9, 2019

Sure

@ijxsid2
Copy link

ijxsid2 commented Jan 22, 2020

Hi @bvaughn, this issue still exists. I can try this one unless someone else is not actively working on it.

@gaearon
Copy link
Member

gaearon commented Feb 27, 2020

Commented: #17889 (review). I don't think this fix is correct.

@jeremyscatigna
Copy link

jeremyscatigna commented Feb 29, 2020

Could I help here ? 🙂

@gaearon
Copy link
Member

gaearon commented Feb 29, 2020

Sure.

@jeremyscatigna
Copy link

jeremyscatigna commented Mar 2, 2020

@gaearon Would it be possible to get some guidance on where to start ? I'm looking at the CodeSandbox provided to start digging in the problem and in the source possibly in ReactPartialRenderer.js and ReactPartialRendererHooks,js. Am I on the right path ?

@bl00mber
Copy link
Contributor

bl00mber commented Mar 16, 2020

Hey @gaearon it seems this bug may be caused by lack of isolation inside ReactPartialRendererHooks.js so when methods are executed they are changing the same variables for both renderers.
If I'll try to isolate these variables within separate class is it will be an acceptable solution?

@gaearon
Copy link
Member

gaearon commented Mar 16, 2020

@jeremyscatigna This sounds right. Are you still working on this?

@hcharley
Copy link

hcharley commented May 12, 2020

I believe this is happening to me using NextJS as well. I'm not sure exactly why the PR hasn't been merged. Not complaining, but just letting maintainers know this appears to be impacting a usecase like mine.

@Charlie85270
Copy link

Charlie85270 commented Dec 11, 2020

No news about this issue ?

@iamandrewluca
Copy link

iamandrewluca commented Jan 2, 2021

My notes on this issue.

This happens only when trying to renderToStaticMarkup(<App />); and inside App there is a useState, useReducer or useMemo that also uses renderToStaticMarkup

e.g.

import React, { useMemo, useReducer, useState } from "react";
import { renderToStaticMarkup } from "react-dom/server";

const hello = <h1>Hello Andrew!</h1>;
const reducer = (state: any) => state;

function App() {
  // Uncomment one of below lines and you will get a error
  // useMemo(() => renderToStaticMarkup(hello), []);
  // useState(() => renderToStaticMarkup(hello));
  // useReducer(reducer, "", () => renderToStaticMarkup(hello));
  return <div />;
}

renderToStaticMarkup(<App />);
TypeError: Cannot set property 'memoizedState' of null

ps: renderToStaticMarkup can be replaced with renderToString, will be same issue
ps2: and if using useRef(renderToStaticMarkup(hello)); another error is showed Invalid hook call. Hooks can only be called...

https://codesandbox.io/s/nervous-liskov-ztt4r?file=/src/index.tsx

@lauchness
Copy link

lauchness commented Jan 19, 2021

I'm having this issue as well using Next.js.

My experience aligns with @iamandrewluca - when using the ReactDOMServer.renderToString() method within a useMemo, I get the error: TypeError: Cannot set property 'memoizedState' of null

@ktfth
Copy link

ktfth commented Apr 28, 2021

I can work on this task? How is the better aproach to test on code base?

@ktfth
Copy link

ktfth commented Apr 28, 2021

I made some changes on related file of ReactPartialRendererHooks check it out 21382

@ktfth
Copy link

ktfth commented Apr 30, 2021

@gaearon Can you help to solve some little details on the pull request process?

@SahilSunda
Copy link

SahilSunda commented May 31, 2021

Is this issue is resolved. @gaearon can you confirm??
Else if not then I can take it and start from now...

@taejs
Copy link

taejs commented Jul 19, 2021

I'll investigate it.

@taejs
Copy link

taejs commented Jul 25, 2021

A reason

  • When renderToString(), renderToStaticMarkup() is triggered, new ReactPartialRenderer is initialized.
  • Hooks execute the parameter, if the parameter is a function.

Look at the code that occurs this error, the ReactPartialRenderer is already initialized to render . #16416 (comment). But useMemo Hook calls processLink() -> renderToStaticMarkup() -> another ReactPartialRenderer is initialized.
For now, those two ReactPartialRenderers are sharing the environment(closure) of ReactPartialRendererHooks.js

UseMemo - ReactFizzHooks.js

// workInProgressHook: {memoizedState : null}
const nextValue = nextCreate();
//this line calls renderToStaticMarkup() - another ReactPartialRenderer is created.

workInProgressHook.memoizedState = [nextValue, nextDeps]; // workInProgressHook is resetted. (become null)

That's why this error has occurred.


There are some ideas to resolve this issue.

  1. Throw an error when the renderer is created more than one.
  2. Change ReactPartialRenderHooks into class, make each ReactPartialRenderer to have a ReactPartialRenderHooks instance.
  3. Create Weakmap using as a key for Component, a value for the environment. Using this environment, Remove reference of Weakmap when finishHooks() called.

@bvaughn @gaearon
If you don't mind, would you share your opinion on which one is the best? Is there a better way to handle this?

@b-smets
Copy link

b-smets commented Aug 9, 2021

Any updates on this ticket?

@eliyamelamed1
Copy link

eliyamelamed1 commented Aug 18, 2021

Mind if I take this?

@SaNsK11
Copy link

SaNsK11 commented Aug 26, 2021

@ambar can I take up this issue if no one is working on it?

@Archies13Singh
Copy link

Archies13Singh commented Aug 30, 2021

Can I take these issue, if no one is working
?

@Lizzyrho21
Copy link

Lizzyrho21 commented Nov 4, 2021

I can take a crack at this issue if nobody else has. Thanks!

@gaearon
Copy link
Member

gaearon commented Nov 4, 2021

@Lizzyrho21

There's been a few attempts to fix it but so far they've tried to address the symptoms rather than the root cause. I think it might be easier for me to look into this, but what would be helpful is a PR with a failing test for this issue. Would you like to create one? ReactServerRendering-test.js might be a good place to add it. Run yarn test --watch ReactServerRendering-test and try to make a test that causes this error.

@iamandrewluca
Copy link

iamandrewluca commented Nov 4, 2021

@gaearon I tried to write a test but it seems it not fails in that environment. Did I miss something 🤔

it('should not crash when used inside useMemo', () => {
  function App() {
    React.useMemo(() => ReactDOMServer.renderToString(<span />), []);
    return <span />;
  }

  expect(() => ReactDOMServer.renderToString(<App />))
    .toThrowError(`Cannot set properties of null (setting 'memoizedState')`)
});
  ● ReactDOMServer › renderToString › should not crash when used inside useMemo

    expect(received).toThrowError(expected)

    Expected substring: "Cannot set properties of null (setting 'memoizedState')"

    Received function did not throw

This piece of code fails in cra browser, cra test, codesandbox and node (using createElement) with same error:

TypeError: Cannot set property 'memoizedState' of null

https://codesandbox.io/s/nervous-liskov-ztt4r?file=/src/index.tsx

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet