Skip to content

Bug: old JSX from previous rendering visible in strict mode #26628

Closed
@MartinGeisse

Description

@MartinGeisse

React version: 18.2.0

I'm having a problem where React seems to show old JSX, i.e. not update the DOM with the latest JSX returned by a component.

The problem can be reproduced in React 18.2.0 with the following sample component. Please note that while this sample code does a few things that are not recommended, such as using global non-state flags and calling setTimeout() directly in the rendering function, to my understanding this should not cause the behaviour I'm getting.

import React, {useState} from "react";

let firstFlag = false;
let secondFlag = false;

export function ReproduceBug() {
  console.log("rendering starts...", firstFlag, secondFlag);
  const [, setDummyState] = useState({ a: "1" });

  console.log("reached first if-statement");
  if (!firstFlag) {
    firstFlag = true;
    setTimeout(() => {
      console.log("timeout fired");
      secondFlag = true;
      setDummyState({ a: "2" });
    }, 500);
  }

  console.log("reached second if-statement");
  if (!secondFlag) {
    console.log("rendering old content");
    return <div>old content</div>;
  }

  console.log("rendering new content");
  return <div>new content</div>;
}

Running this code prints on the console:

rendering starts... false false
ReproduceBug.js:10 reached first if-statement
ReproduceBug.js:20 reached second if-statement
ReproduceBug.js:22 rendering old content
ReproduceBug.js:7 rendering starts... true false
ReproduceBug.js:10 reached first if-statement
ReproduceBug.js:20 reached second if-statement
ReproduceBug.js:22 rendering old content
ReproduceBug.js:14 timeout fired
ReproduceBug.js:7 rendering starts... true true
ReproduceBug.js:10 reached first if-statement
ReproduceBug.js:20 reached second if-statement
ReproduceBug.js:26 rendering new content
ReproduceBug.js:7 rendering starts... true true
ReproduceBug.js:10 reached first if-statement
ReproduceBug.js:20 reached second if-statement
ReproduceBug.js:26 rendering new content

So it seems to me that the latest rendered JSX should contain the words "new content", yet the DOM still contains "old content".

The problem only occurs in strict mode.

Addendum: One might suggest that the mount-unmount-remount cycle in strict mode somehow causes this problem. While I don't argue against this being the case, I'd argue that it SHOULD NOT be the case: The 500ms timeout causes a re-render long after the remounting is finished, and does not carry over any data. The global flags do carry over data, but they are logged to prove that they do not confuse the rendering code. Yet, after the timeout, the rendering code runs again (twice), returns the new content, but the DOM stays at the old content. Even the expected behaviour of the remounting cycle in strict mode does not explain this behaviour, hence my assumption that this is a bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Status: UnconfirmedA potential issue that we haven't yet confirmed as a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions