Skip to content

Bug: "Internal React error: Expected static flag was missing." #34111

@Scriptor25

Description

@Scriptor25

"Internal React error: Expected static flag was missing. Please notify the React team."

This error message appeared after I created the component in the following code example. I pinpointed the issue down to the recursive nature of the component, which seems to confuse react in a way that it does not handle the early return before the calls to react hooks (which I placed there by accident) correctly.

"use client";

import { useEffect, useState } from "react";

/* dummy type */
type ProductGroup = { id: string, name: string };

type SubGroupProps = {
    depth: number,
    label: string,
    root: ProductGroup[],
    action: (id: string) => Promise<ProductGroup[]>,
}

/* create recursive subgroups to select from */
function SubGroupFilter({ depth, label, root, action }: Readonly<SubGroupProps>) {

    /* ------- BUG FROM HERE ------- */

    /* early return */
    if (!root.length)
        return;

    /* does not get catched!! */

    const [index, setIndex] = useState<number>(0);
    const [items, setItems] = useState<ProductGroup[]>([]);

    useEffect(() => {
        action(root[index].id).then(setItems);
    }, [root, action, index, setItems]);

    /* ---------- TO HERE ---------- */

    return (
        <>
            <fieldset>
                <legend>{label}</legend>
                <select name="product-group" onChange={event => setIndex(event.currentTarget.selectedIndex)}>
                    {root.map(item => (
                        <option key={item.id} value={item.id}>
                            {item.name}
                        </option>
                    ))}
                </select>
            </fieldset>
            <SubGroupFilter depth={depth + 1} label={`Subgroup - ${root[index].name}`} root={items} action={action} />
        </>
    );
}

type SearchFormProps = {
    root: ProductGroup[],
    action: (id: string) => Promise<ProductGroup[]>,
}

export function SearchForm({ root, action }: Readonly<SearchFormProps>) {
    return (
        < >
            <span >Search Form</span>
            <form>
                <SubGroupFilter depth={0} label="Product groups" root={root} action={action} />

                <button className="button">search</button>
            </form>
        </>
    );
}
<SearchForm root={[{
          id: "foo1",
          name: "Foo1"
        }, {
          id: "foo2",
          name: "Foo2"
        }, {
          id: "foo3",
          name: "Foo3"
        }, {
          id: "foo4",
          name: "Foo4"
        }, {
          id: "foo5",
          name: "Foo5"
        }]} action={async (id: string) => {
          "use server";

          if (id === "foo1" || id === "foo1-foo2" || id === "foo1-foo2-foo3")
            return [{
              id: `${id}-foo1`,
              name: "Foo1"
            }, {
              id: `${id}-foo2`,
              name: "Foo2"
            }, {
              id: `${id}-foo3`,
              name: "Foo3"
            }, {
              id: `${id}-foo4`,
              name: "Foo4"
            }, {
              id: `${id}-foo5`,
              name: "Foo5"
            }];

          return [];
        }}>
</SearchForm>

React version: 19.1.0

Steps To Reproduce

  1. create a new component with recursive subcomponents (like here with the filter subgroups)
  2. make those recursive subcomponents call react hooks after an early return

In the example provided above the error message pops up every time a new subgroup appears, after selecting a parent group.

The issue does not appear when properly calling react hooks, i.e. move the return after the block of hook calls.

The current and expected behavior

There is seemingly no change in behavior, nor any other issues except for the error message.

Hope this bug report somehow helps fixing the issue and make React a little better than it already is.

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