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

TypeScript error when using useFormState #56041

Closed
leerob opened this issue Sep 26, 2023 · 30 comments
Closed

TypeScript error when using useFormState #56041

leerob opened this issue Sep 26, 2023 · 30 comments
Labels
locked TypeScript Related to types with Next.js. Upstream Related to using Next.js with a third-party dependency. (e.g., React, UI/icon libraries, etc.).

Comments

@leerob
Copy link
Member

leerob commented Sep 26, 2023

Hey folks, leaving an issue open here in case people search for this. Currently, there's a TS error you can safely ignore when importing useFormState. This is dependent on an upstream issue being merged: DefinitelyTyped/DefinitelyTyped#66726

Example

'use client'
 
 // @ts-ignore
import { experimental_useFormState as useFormState } from 'react-dom'
import { experimental_useFormStatus as useFormStatus } from 'react-dom'
import { createTodo } from '@/app/actions'
 
const initialState = {
  message: null,
}
 
function SubmitButton() {
  const { pending } = useFormStatus()
 
  return (
    <button type="submit" aria-disabled={pending}>
      Add
    </button>
  )
}
 
export function AddForm() {
  const [state, formAction] = useFormState(createTodo, initialState)
 
  return (
    <form action={formAction}>
      <label htmlFor="todo">Enter Task</label>
      <input type="text" id="todo" name="todo" required />
      <SubmitButton />
      <p aria-live="polite" className="sr-only">
        {state?.message}
      </p>
    </form>
  )
}
@pawelblaszczyk5
Copy link

Linking other issue where workaround has been mentioned 😃 #55919

@balazsorban44 balazsorban44 added Upstream Related to using Next.js with a third-party dependency. (e.g., React, UI/icon libraries, etc.). TypeScript Related to types with Next.js. labels Sep 29, 2023
@esponges
Copy link

What if i'd wanted to pass arguments to createTodo? It's not clear how to type in the docs, and since there are no type declarations yet 🤔

ronilsonalves added a commit to ronilsonalves/5lnk that referenced this issue Sep 29, 2023
– Removed file react.d.ts created to handle open issue vercel/next.js#56041 (comment) and the file defined the type for useFormState broke the React types.
@Nechir-89
Copy link

I used

// @ts-expect-error
import { experimental_useFormState as useFormState } from 'react-dom'

and this error displayed in the terminal

Attempted import error: 'experimental_useFormState' is not exported from 'react-dom' (imported as 'useFormState').

@ronilsonalves
Copy link

I used

// @ts-expect-error

import { experimental_useFormState as useFormState } from 'react-dom'

and this error displayed in the terminal

Attempted import error: 'experimental_useFormState' is not exported from 'react-dom' (imported as 'useFormState').

Did you tried to comment with //@ts-ignore ? Are you using Next.js >13.5 version?

Here //@ts-ignore running with this version have worked.

@Nechir-89
Copy link

I used

// @ts-expect-error

import { experimental_useFormState as useFormState } from 'react-dom'

and this error displayed in the terminal

Attempted import error: 'experimental_useFormState' is not exported from 'react-dom' (imported as 'useFormState').

Did you tried to comment with //@ts-ignore ? Are you using Next.js >13.5 version?

Here //@ts-ignore running with this version have worked.

I did try @ts-ignore and got the same error, im having v13.4, do you think the only solution is to update next to v13.5

@pawelblaszczyk5
Copy link

I used
// @ts-expect-error
import { experimental_useFormState as useFormState } from 'react-dom'
and this error displayed in the terminal
Attempted import error: 'experimental_useFormState' is not exported from 'react-dom' (imported as 'useFormState').

Did you tried to comment with //@ts-ignore ? Are you using Next.js >13.5 version?
Here //@ts-ignore running with this version have worked.

I did try @ts-ignore and got the same error, im having v13.4, do you think the only solution is to update next to v13.5

13.4 uses older experimental React version which don’t include this hook. So you need to upgrade to 13.5 to use it 😃

@esponges
Copy link

esponges commented Oct 3, 2023

I used
// @ts-expect-error
import { experimental_useFormState as useFormState } from 'react-dom'
and this error displayed in the terminal
Attempted import error: 'experimental_useFormState' is not exported from 'react-dom' (imported as 'useFormState').

Did you tried to comment with //@ts-ignore ? Are you using Next.js >13.5 version?
Here //@ts-ignore running with this version have worked.

I did try @ts-ignore and got the same error, im having v13.4, do you think the only solution is to update next to v13.5

13.4 uses older experimental React version which don’t include this hook. So you need to upgrade to 13.5 to use it 😃

13.5.4 (latest) still throws the error, I tried rm -rf node_modules && npm i before posting this.

@meech-ward
Copy link

rm -rf .next

@rfackroyd
Copy link

Hey all, make sure you use the next.config.js setting to enable Server Actions:

module.exports = {
  experimental: {
    serverActions: true,
  },
}

This fixed it for me (I should have set it up front anyway) and explained the error well.

@JoshWilliams92
Copy link

I was having the same issue with next.js 13.4. I manually installed next@latest react@latest react-dom@latest and the issue persists. After adding // @ts-ignore on the file above import { experimental_useFormState as useFormState } from "react-dom" seemed to fix the issue for me.

@ctjlewis
Copy link
Contributor

ctjlewis commented Oct 11, 2023

Workaround

For now, just pin these versions of the types packages and the { experimental_... } exports will be recognized by TS:

{
  "@types/react": "18.2.23",
  "@types/react-dom": "18.2.8",
}

@BaileySimrell
Copy link

Screenshot 2023-10-13 at 8 29 07 PM

I'm able get the import error to go away with ts-ignore, however can't get this thing to compile

Screenshot 2023-10-13 at 8 29 20 PM

@yafkari
Copy link

yafkari commented Oct 16, 2023

Error still occuring in next.js 13.5.5.

This made the trick for now:

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
import { experimental_useFormStatus as useFormStatus } from "react-dom";

@Nlferu
Copy link

Nlferu commented Oct 18, 2023

Hello guys

To fix linting error I have just changed below packages from:

    "react": "^18",
    "react-dom": "^18",
    "@types/react": "^18",
    "@types/react-dom": "^18",

Into:

    "react": "18.2.0",
    "react-dom": "18.2.0",
    "@types/react": "18.2.14",
    "@types/react-dom": "18.2.6",

@morellodev
Copy link
Contributor

Hi all, the issue still persists on next@13.5.6 and @types/react-dom@18.2.14.

In particular, @types/react-dom@18.2.14 declares useFormState and useFormStatus as exported members of react-dom, so the following works at the type level:

import { useFormState, useFormStatus } from "react-dom";

but at runtime both of them are undefined.

To make things work, I still have to use this workaround:

import {
  // @ts-expect-error
  experimental_useFormState as useFormState,
  // @ts-expect-error
  experimental_useFormStatus as useFormStatus,
} from "react-dom";

but doing so breaks the type inference on useFormState usage:

const [formState, formAction] = useFormState(action, initialState);
//     ^ any      ^ any

@jmd01
Copy link

jmd01 commented Oct 19, 2023

@morellodev try adding "types": ["react-dom/experimental"] to your tsconfig.json

{
  "compilerOptions": {
    ...
    "types": ["react-dom/experimental"],
  }

And then use the import as normal:

// MyForm.tsx
import { useFormState } from 'react-dom'
import { useFormStatus } from 'react-dom'

I'm using the following versions:

  "devDependencies": {
    "@types/react-dom": "18.2.13",
    ...
  }

@shawnmclean
Copy link

shawnmclean commented Oct 19, 2023

@jmd01 following exactly that.

Unhandled Runtime Error
TypeError: (0 , react_dom__WEBPACK_IMPORTED_MODULE_3__.useFormState) is not a function or its return value is not iterable
import { useFormState } from "react-dom";
"react": "18.2.0",
"react-dom": "18.2.0",

@morellodev
Copy link
Contributor

@jmd01 @shawnmclean The issue we are having is due to a misalignment between the members exported by react-dom and the types definitions from @types/react-dom.

The canary react-dom version shipped with Next.js exports useFormState and useFormStatus with the experimental_ prefix, while the type defs say they are not prefixed.

@jmd01
Copy link

jmd01 commented Oct 19, 2023

@shawnmclean @morellodev I had to also use the latest next, react, react-dom. This is working for me now:

    "@types/react": "18.2.29",
    "@types/react-dom": "18.2.13",
    "react": "experimental",
    "react-dom": "experimental",
    "next": "canary",

https://github.com/jmd01/next-forms

@KushibikiMashu
Copy link

@jmd01
Thanks! This is also working 👍

{
  "dependencies": {
    "next": "canary",
    "react": "18.2.0",
    "react-dom": "18.2.0"
  },
  "devDependencies": {
    "@types/react": "18.2.30",
    "@types/react-dom": "18.2.14",
  }
}

@neatonk
Copy link

neatonk commented Oct 20, 2023

As an alternative to the above workarounds, you can use this shim with next@13.5.6:

// file: react-dom-shim.ts
import {
  //@ts-expect-error
  experimental_useFormState,
  //@ts-expect-error
  experimental_useFormStatus,
  // types are defined, but exports are not :(
  useFormState as undefined_useFormState,
  useFormStatus as undefined_useFormStatus
} from "react-dom"

export const useFormState = experimental_useFormState as typeof undefined_useFormState
export const useFormStatus = experimental_useFormStatus as typeof undefined_useFormStatus

@morellodev
Copy link
Contributor

Nice trick @neatonk 👍 BTW, I find a little odd that we have to do all sorts of workarounds in order to get things work, and it is even odder that the official docs and examples from Vercel are misleading.

@Jacob-Daniel
Copy link

Jacob-Daniel commented Oct 27, 2023

Since updating to Next.js 14, the TS runtime error persisted when importing 'experimental_useFormState':

// @ts-ignore
import { experimental_useFormState as useFormState } from 'react-dom'

However, the error goes away when removing 'experimental_useFormState':

// @ts-ignore
import { useFormState, useFormStatus } from "react-dom";

We still need ''ts-ignore' otherwise get:

Module '"react-dom"' has no exported member 'useFormState'.

package.json:

"@types/react": "18.2.23",
"@types/react-dom": "18.2.8",

@omburj
Copy link

omburj commented Nov 2, 2023

for https://github.com/vercel/next.js/tree/canary/examples/next-forms
correcting the verion of reac-dom to latest resolves the pnpm run build error
"@types/react": "^18.2.34",
"@types/react-dom": "^18.2.14",

OR
option 2 use what @leerob prescribed above add
2.1
// @ts-ignore
to the start of add-form.tsx and delete-form.tsx
2.2
and replace experimental_useFormState with useFormState
//import { experimental_useFormState as useFormState } from 'react-dom'
//import { useFormStatus } from 'react-dom'
2.3
and finally remove experimental serverrun from next.config.js making it simple 3 lines as below
/** @type {import('next').NextConfig} */
const nextConfig = {}
module.exports = nextConfig

omburj added a commit to omburj/next-forms that referenced this issue Nov 2, 2023
corrected code on top of  https://github.com/vercel/next.js/tree/canary/examples/next-forms
the change is in react-dom type version to 18.2.14
"@types/react": "^18.2.34",
"@types/react-dom": "^18.2.14",

refer for detailed problem details and other work arounds suggested by NextJS auhtor and others
vercel/next.js#56041
@leerob
Copy link
Member Author

leerob commented Nov 2, 2023

Yeah, I'd recommend just upgrading to the latest versions for the new types 😄

@omburj
Copy link

omburj commented Nov 3, 2023 via email

@havgry
Copy link

havgry commented Nov 7, 2023

I'm running into Module '"react-dom"' has no exported member 'useFormStatus' with @types/react-dom@18.2.14 while 18.2.13 seems to work just fine suggesting it might be more complicated than just updating to the latest versions to resolve the type error. This combination works for me:

"@types/react": "18.2.36",
"@types/react-dom": "18.2.13",

Just putting it out there in case it helps someone else.

@rush86999
Copy link

upgrading to the latest versions does not work. 👎

masonmcelvain added a commit to masonmcelvain/simple-secret-santa that referenced this issue Dec 23, 2023
@leerob
Copy link
Member Author

leerob commented Dec 30, 2023

I've confirmed everything now works on the latest version of Next.js + types, and updated our example as well.

#60052

If you are still seeing an issue, please restart your TS server or ensure you have the right TS server selected in your IDE, as there might be multiple.
CleanShot 2023-12-30 at 14 19 24@2x

@leerob leerob closed this as completed Dec 30, 2023
Copy link
Contributor

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
locked TypeScript Related to types with Next.js. Upstream Related to using Next.js with a third-party dependency. (e.g., React, UI/icon libraries, etc.).
Projects
None yet
Development

No branches or pull requests