Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot assign to 'state' because it is a constant or a read-only property

When I do a search on this issue, I can only find questions that modify this.state directly somewhere in a method body instead of using this.setState(). My problem is that I want to set a starting state in the constructor as follows:

export default class Square extends React.Component<any, any> {   constructor(props: any) {     super(props);     this.state = {       active: false     };   }    public render() {     ...   } } 

The app fails to start with the following compile error:

Cannot assign to 'state' because it is a constant or a read-only property 

And this is because in definition of React.Component we have:

readonly state: null | Readonly<S>; 

So I'm not sure how to go about this. The official react tutorial in JS directly assigns to this.state and says that it is an acceptable pattern to do so in the constructor, but I can't figure out how to do this with TypeScript.

like image 583
jeanluc Avatar asked Jun 28 '18 03:06

jeanluc


People also ask

Can't assign to current because it is a read only property?

The error "Cannot assign to 'current' because it is a read-only property" occurs when we initialize a ref with a null value and don't include null in its type. To solve the error, include null in the ref's type, e.g. const ref = useRef<string | null>(null) .

How do you assign a value to a readonly property in TypeScript?

The TypeScript error "Cannot assign to read only property of object" occurs when we try to change a property of a frozen object or when a property has been defined with Object. defineProperties() . To solve the error, create a copy of the object or array, or set the property to writable .

How do you set a state React?

The setState() Method State can be updated in response to event handlers, server responses, or prop changes. This is done using the setState() method. The setState() method enqueues all of the updates made to the component state and instructs React to re-render the component and its children with the updated state.

Does not exist on type readonly?

js error "Property does not exist on type 'Readonly<{}>'" occurs when we try to access the props or state of a class component which we haven't typed. To solve the error, use the generic on the React. Component class to type the props or state objects of the class.


2 Answers

Before rolling back (as suggested by @torvin's answer), please read through https://github.com/DefinitelyTyped/DefinitelyTyped/pull/26813#issuecomment-400795486.

This was not meant to be a regression - the solution is to use state as a property. It is better than previous approach (setting state in a constructor) because:

  • you don't need constructor at all anymore
  • you can't forget to initialize state (it is now a compile-time error)

For example:

type Props {}  type State {   active: boolean }  export default class Square extends React.Component<Props, State> {   public readonly state: State = {     active: false   }    public render() {     //...   } } 

Another approach:

type Props {}  const InitialState = {   active: false }  type State = typeof InitialState  export default class Square extends React.Component<Props, State> {   public readonly state = InitialState    public render() {     //...   } } 
like image 110
Nikola Mihajlović Avatar answered Nov 04 '22 00:11

Nikola Mihajlović


This appears to be a recent change in @types/react introduced in commit 542f3c0 which doesn't work very well, considering the fact that Typescript doesn't support assigning parent's readonly fields in derived constructors.

I suggest rolling back to a previous version of @types/react. Version 16.4.2 appears to be the last one before the unfortunate change has been made.

You can pin the version by removing the ^ in your package.json:

"devDependencies": {   ...   "@types/react": "16.4.2", 

Also check out the discussion about this change on DefinitelyTyped github pull request page

like image 34
torvin Avatar answered Nov 03 '22 23:11

torvin