react icon indicating copy to clipboard operation
react copied to clipboard

Bug: Internal React error: Expected static flag was missing

Open Developer-Nijat opened this issue 3 years ago • 24 comments

React version: V18.0.0 React router DOM: V5.2.1

Steps To Reproduce

  1. Going to profile page
  2. Warning: Internal React error: Expected static flag was missing. Please notify the React team.

Link to code example: Screenshot 2022-04-17 124859 DynamicFilter.js component Screenshot 2022-04-17 125107

The current behavior

The expected behavior

Developer-Nijat avatar Apr 17 '22 08:04 Developer-Nijat

Please provide a reproducible example. Either on GitHub or a sandbox. Otherwise we can’t really fix this. Thanks!

gaearon avatar Apr 17 '22 17:04 gaearon

Please provide a reproducible example. Either on GitHub or a sandbox. Otherwise we can’t really fix this. Thanks!

Probably it is not possible. Because this is the large project and totally code sharing is prohibited. It is understandable, React v18 is not good for old projects.

Developer-Nijat avatar Apr 17 '22 19:04 Developer-Nijat

It is understandable, React v18 is not good for old projects.

That's absolutely not correct. We're running huge codebases from 2013-2014 with almost no changes on React 18. The error is just a bug in React that will be easy to fix as soon as somebody gives us a reproducible example.

Probably it is not possible. Because this is the large project and totally code sharing is prohibited.

Usually the way you can do this is by deleting code until you're left with a small example that doesn't contain any app-specific logic.

gaearon avatar Apr 17 '22 20:04 gaearon

@gaearon Here's a small test repo, that will reproduce the bug. https://github.com/orangecoding/react-static-flag-exception

orangecoding avatar Apr 22 '22 07:04 orangecoding

Thank you! This example seems to use a Hook conditionally — it (data) useStyles(). This is not supported in React. If you use Hooks you need to either follow rules or use the linter rule which forbids this.

gaearon avatar Apr 22 '22 11:04 gaearon

Yeah I know this. Unfortunatelly lot's of ppl doesn't seem to know this and this is a common thing that I'm seeing throughout a lot of libs. I copied this particular issue from here: https://github.com/farahat80/react-open-weather/blob/master/src/js/components/ReactWeather.js#L20

Going back to react 17, these things work without any issues...

orangecoding avatar Apr 22 '22 11:04 orangecoding

It works accidentally and likely breaks in other cases. But we do need a better error. I would’ve expected “rendered more hooks than last time” error to appear.

gaearon avatar Apr 22 '22 12:04 gaearon

I fear that when this is going to be thrown as an error (which it actually is, no discussion here), a lot of external libs will be broken. However not sure if this is the only case where such an error occurs. Maybe @Developer-Nijat can check this with his code as well?

orangecoding avatar Apr 22 '22 18:04 orangecoding

I fear that when this is going to be thrown as an error (which it actually is, no discussion here), a lot of external libs will be broken. However not sure if this is the only case where such an error occurs. Maybe @Developer-Nijat can check this with his code as well?

First of all, let's say this is not understandable error. We can't figure out where the error is. Again there is a high risk of errors in the next days. Currently v18 is risk for large projects. I will check this error again but

Developer-Nijat avatar Apr 22 '22 18:04 Developer-Nijat

The issue is exactly as what @gaearon said. In my case, the very first line of the component was checking a prop 'hidden' and returning a fragment if it is true. That was causing this error. Though it was not a best practice, V17 was OK with this.

SidebarItem.tsx Issue: image

The fix was to do the check after initiating the hook.

Fix: image

firoz2580 avatar Apr 24 '22 09:04 firoz2580

Reproducible if an additional useEffect was called: https://codesandbox.io/s/conditional-useeffect-static-flag-was-missing-gg94qy

An additional useState will throw the expected "rendered more hooks than expected" error.

In React 17, no error is logged nor thrown: https://codesandbox.io/s/react-17-conditional-useeffect-static-flag-was-missing-forked-qbgm67

eps1lon avatar Apr 24 '22 09:04 eps1lon

Though it was not a best practice, V17 was OK with this.

I want to make it clear that it worked accidentally and in a narrow range of circumstances. You should absolutely not rely on this. For example, any person who adds state to the corresponding custom Hook would break every component relying on this even in 17.

I agree it’s a problem that the error is unclear and removed from the actual case. That has to be fixed.

But this has nothing to do with 18. If your code relies on this, it is extremely fragile in 17. Enable the linter and fix it.

gaearon avatar Apr 24 '22 18:04 gaearon

Enable the linter and fix it. As I said, I saw these things in at least 2 external debts (one of which is semantic-ui-react which has millions of downloads). So yeah, I agree it kinda has to be fixed by the vendor, however I guess this deserves some major communication efforts, coz otherwise ppl will most likely not update their libs (I guess)

orangecoding avatar Apr 25 '22 06:04 orangecoding

I had the same warning migrating from v17 to v18:

Before

const C = () =>  {
    if (condition) return null;
    useEffect(() => {/*...*/}, []);
    return <div></div>
}

After

const C = () =>  {
    useEffect(() => {/*...*/}, []);
    if (condition) return null;
    return <div></div>
}

The above change solved.

Thanks.

FabrizioArmango avatar Apr 30 '22 10:04 FabrizioArmango

I can confirm, I get the same error: "Expected static flag was missing. Please notify the React team." with the code below:

import React, { useMemo } from "react";
import { useTable, useSortBy, usePagination } from "react-table";

const JSONTable = ({ arr }: { arr?: object[] }) => {

  if (!arr?.length) return null;

  const data = useMemo(() => arr, [arr]);

  const keys = Object.keys(arr[0]);

  const columns = useMemo(
    () => keys.map((key) => ({ Header: key, accessor: key })),
    [arr]
  );

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    page, // Instead of using 'rows', we'll use page,
    // which has only the rows for the active page

    // The rest of these things are super handy, too ;)
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,
    state: { pageIndex, pageSize },
  } = useTable(
    { columns, data, initialState: { pageIndex: 0 } },
    useSortBy,
    usePagination
  );

  return null;
}

However, I stop getting the error when I remove the following code below:

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    page, // Instead of using 'rows', we'll use page,
    // which has only the rows for the active page

    // The rest of these things are super handy, too ;)
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,
    state: { pageIndex, pageSize },
  } = useTable(
    { columns, data, initialState: { pageIndex: 0 } },
    useSortBy,
    usePagination
  );

joeelmahallawy avatar May 19 '22 04:05 joeelmahallawy

The issue is the early return. Put the return after calls to Hooks. Please add the linter to your setup to detect these issues at compile time as originally intended.

gaearon avatar May 19 '22 10:05 gaearon

The issue is the early return. Put the return after calls to Hooks. Please add the linter to your setup to detect these issues at compile time as originally intended.

Bad case: https://codepen.io/ahuigo/pen/YzOVPQv

ahuigo avatar Mar 02 '23 18:03 ahuigo

Just ran at this error trying to validate forms within Modal with zod validation library and react hook form. Basically the error was coming when I was checking (conditional rendering) for the modal and I was doing before the useForm hook of react-hook-form.

The lesson here is: when you have any kind of hooks always do your conditional renderings at the bottom right before returning your jsx/tsx!

3mper0r avatar Jun 19 '23 19:06 3mper0r

The issue is exactly as what @gaearon said. In my case, the very first line of the component was checking a prop 'hidden' and returning a fragment if it is true. That was causing this error. Though it was not a best practice, V17 was OK with this.

SidebarItem.tsx Issue: image

The fix was to do the check after initiating the hook.

Fix: image

totally solved my problem.

I had in code

    if (!visible) return null;
    const proModal = useProModal();

and just moved up of component return:

    const proModal = useProModal();
    if (!visible) return null;

vilelalabs avatar Aug 26 '23 02:08 vilelalabs

Similar issue here. I am using react-native-web:

"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.71.8",
"react-native-web": "~0.18.10",

Is a simple hook that does this:

    const [cards, setCards] = useState([])

    useEffect(() => {
        ;(async () => {
            try {
                const cards = await Server.userCards({ user_id })
                setCards(cards)
            } catch (error) {
                //
            }
        })()
    }, [user_id, setCards])

If a comment the line setCards(cards) I don't get any error.

react-dom.development.js:86 Warning: Internal React error: Expected static flag was missing. Please notify the React team.
    at Deck (http://localhost:19006/static/js/bundle.js:27119:20)
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:33953:45
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:33953:45
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:33953:45
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:33953:45
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:33953:45
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:9361:24
    at ScrollView (http://localhost:19006/static/js/bundle.js:39905:37)
    at ScrollView
    at http://localhost:19006/static/js/bundle.js:33953:45
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:33953:45
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:33953:45
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:7859:24
    at http://localhost:19006/static/js/bundle.js:33953:45
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:33953:45
    at Lobby (http://localhost:19006/static/js/bundle.js:26652:23)
    at Cards (http://localhost:19006/static/js/bundle.js:27938:79)
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:33953:45
    at div
    at http://localhost:19006/static/js/bundle.js:13035:25
    at http://localhost:19006/static/js/bundle.js:33953:45
    at Views (http://localhost:19006/static/js/bundle.js:25587:79)
    at App (http://localhost:19006/static/js/bundle.js:25525:70)
    at withDevTools(App)

Josema avatar Sep 27 '23 07:09 Josema

Getting this when using @sentry/react.

import { captureRemixErrorBoundaryError, withSentry } from '@sentry/remix';

const Root = () => {};

const RootWithSentry = withSentry(Root);

export default Root;

adaboese avatar Jan 11 '24 15:01 adaboese

@adaboese I'm not able to reproduce that example in a new Remix project, can you provide a full repro? I want to rule out the known issue above that hooks are being called conditionally.

rickhanlonii avatar Jan 11 '24 15:01 rickhanlonii

@adaboese I'm not able to reproduce that example in a new Remix project, can you provide a full repro? I want to rule out the known issue above that hooks are being called conditionally.

That turned out to be a false-positive.

Although I am not clear why adding/removing withSentry caused the issue/made it go away, but I am pretty sure that the issue is actually with this package. https://github.com/edmundhung/conform/issues/375#issuecomment-1887514277

adaboese avatar Jan 11 '24 17:01 adaboese

This is an important issue to fix, although with a little bit of googling you can figure out what is causing this error, having a proper error message would allow React to tell the developer where they should look for their conditional hooks to fix, as right now it's a bit of a pain to figure out where to look.

andylovescode avatar May 24 '25 01:05 andylovescode

`import { RootState, useAppSelector } from "@/store";

export const getLocationNameById = (id: number | string): string => { const { locations } = useAppSelector((state: RootState) => state.locations); const location = locations.find( (location) => location.posID === parseInt(String(id), 10) || location.posID === id ); return location ? location.locationName : "Unknown Location"; };`

I am getting the same error ERROR Warning: Internal React error: Expected static flag was missing. Please notify the React team. when calling getLocationNameById this function.

Owhab avatar Oct 15 '25 09:10 Owhab