How to correctly set initial state in React with Typescript without constructor?
Am I doing it the correct way?
Yes.
Is setting class property directly considered a bad style in Typescript?
No.
A slightly better approach
Consider declaring state as public readonly
, and using the Readonly modifier.
This will satisfy TSLint while also giving you some protection against being modified incorrectly (ie. not using this.setState
).
Even though state is still exposed to the outside, this is never usually a problem.
interface IState {
value: number;
}
class App extends React.Component<{}, IState> {
public readonly state: Readonly<IState> = {
value: 10
}
public render() {
return <div>{this.state.value}</div>
}
}
The TSLint rule
Declaring access modifiers explicitly is a good thing, even if it results in the same access implicitly. It helps keep your code clear, so I wouldn't disable this TSLint rule.
Related videos on Youtube
John
Updated on June 04, 2022Comments
-
John almost 2 years
In modern JS, we can directly set an initial state for a React component like this:
class App extends React.Component { state = {value: 10} render() { return <div>{this.state.value}</div> } }
When I am trying to do this with Typescript, TSLint says "The class property 'state' must be marked either 'private', 'public', or 'protected'". If I set it to "private", the linter will report
Class 'App' incorrectly extends base class 'Component<{}, { value: number; }, any>'. Property 'state' is private in type 'App' but not in type 'Component<{}, { value: number; }, any>'.
onApp
. I am aware that I can tweak the linter rules to skip this kind of checks, but checking the visibility of class properties in general is a good thing I want to utilize.After testing out all three options, only choosing "public" won't get TSLint throw out errors. But since the state here represents the internal state of this specific component, setting it to public seems pretty weird. Am I doing it the correct way?
class App extends React.Component<{}, { value: number }> { public state = { value: 10 }; public render() { return <div>{this.state.value}</div>; } }
In all TS-React tutorials I've found online, a constructor is used, like in the old JS syntax.
class App extends React.Component<{}, { value: number }> { constructor(props: any) { super(props); this.state = { value: 10 }; } public render() { return <div>{this.state.value}</div>; } }
Is setting class property directly considered a bad practice/style in Typescript?
-
Estus Flask over 5 years@cartant OP states that first snippet produces linter error. This suggests that there's lint rule to specify the visibility explicitly (I didn't ever notice such rule because it seems to be useless).
-
-
John over 5 yearsYes I agree. I looked into the type definitions of React.Component, state seems to be not annotated, so
public
here should be the right keyword to use indeed :) -
Maksim Nesterenko over 3 yearsState is read-only in react types by default. No need to apply your own read-only on top.
-
rshepp over 3 years"No need to apply your own read-only on top." - incorrect. Without declaring state as
readonly
, the compiler will allow code that entirely replaces state, eg.this.state = { value: 10 };
. And, without using theReadonly
modifier, the compiler will allow code that improperly updates state members, eg.this.state.value = 10;
. Try it yourself and you'll see without these modifiers the compiler won't protect you from doing the wrong thing. -
Maksim Nesterenko over 3 years
readonly state = {}
is ok. Though Readonly is excess. See: github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/…