question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Bug: useState with class as initial state throws an error

See original GitHub issue

Using a JavaScript class as initial state in useState throws an error. This is because mountState check if the initial state is a function by typeof initialState === 'function' and classes are technically functions. However since ES6+, I feel like most developers don’t consider classes functions because of the less prototype-inheritance feel since ES6 and the class keyword.

React version: 17.0.2

Steps To Reproduce

  1. Define an ES6 class
  2. Use the class as initialState argument to useState

Code example:

import { useState } from "react";
import ReactDOM from "react-dom";

class A {}

function App() {
  const [cls, setCls] = useState(A);
  return <h2>{cls.name}</h2>;
}

ReactDOM.render(<App />, document.body);

The current behavior

TypeError: Cannot call a class as a function
    at _classCallCheck (eval at z (eval.js:42), <anonymous>:3:11)
    at A (VM302 index.js:19)
    at mountState (react-dom.development.js:10436)
    at Object.useState (react-dom.development.js:10919)
    at useState (react.development.js:954)
    at App (VM302 index.js:25)

Alternatively, the error can be TypeError: Class constructor X cannot be invoked without 'new'.

The expected behavior

As mentioned in the description above, I would

  • either expect classes to work
  • or mention this caveat in the docs.

I guess checking, if the initial state is actually a non-class function, could cause instances of subclasses of functions not to work (depending how the check is done).

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
gaearoncommented, Mar 24, 2021

I’d like to see a PR that warns if setState or useState is passed a function whose first letter is capital. That’s enough of a hint to find the common cases.

1reaction
bvaughncommented, Mar 23, 2021

I don’t consider this a bug.

As the issue description mentions, useState supports two formats:

  1. Eagerly initialize the value (e.g. useState('value'))
  2. Lazily initialize the value with a function (e.g. useState(() => 'value'))

React decides which one you’ve done using the typeof operator. (I am not aware of an alternative to this approach but please feel free to share one if you have an idea.)

In JavaScript, the typeof a class is "function" so React thinks you’re using the second format and tries to call the “function” which causes an error to be thrown. To fix this, you can wrap your class value with a function, like so:

useState(() => A);

I’ll tag this as a discussion for now, but I’m not sure this is something that we’ll change.

Read more comments on GitHub >

github_iconTop Results From Across the Web

5 Most Common useState Mistakes React Developers Often ...
The problem is that useState allows you to define its initial state using anything you want.
Read more >
Why does setState callback throw an error: "State updates ...
1 Answer 1 · Tried that. Error: React Hook "useEffect" cannot be called inside a callback. React Hooks must be called in a...
Read more >
React Hooks cheat sheet: Best practices with examples
Declaring a state variable is as simple as calling useState with some initial state value, like so: useState(initialStateValue) . const ...
Read more >
Hooks FAQ - React
They let you use state and other React features without writing a class. ... classes to Hooks unless you planned to rewrite them...
Read more >
react-hydration-error - Next.js
function MyComponent() { // This condition depends on `window`. ... useState } from 'react' function MyComponent() { // The default value is 'blue', ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found