在现代JS中,我们可以像这样直接为React组件设置初始状态:
class App extends React.Component {
state = {value: 10}
render() {
return <div>{this.state.value}</div>
}
}
当我尝试使用Typescript进行此操作时,TSLint说“必须将类属性'state'标记为'private','public'或'protected'”。如果我将其设置为“私有”,则短绒将在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>'.
上报告App
。我知道我可以调整linter规则以跳过这种检查,但是总体上检查类属性的可见性是我想利用的。
测试完所有三个选项之后,仅选择“ public”将不会得到TSLint抛出错误。但是,由于这里的状态代表此特定组件的内部状态,因此将其设置为public似乎很奇怪。我做对了吗?
class App extends React.Component<{}, { value: number }> {
public state = { value: 10 };
public render() {
return <div>{this.state.value}</div>;
}
}
在网上找到的所有TS-React教程中,都使用了构造函数,就像旧的JS语法一样。
class App extends React.Component<{}, { value: number }> {
constructor(props: any) {
super(props);
this.state = { value: 10 };
}
public render() {
return <div>{this.state.value}</div>;
}
}
在Typescript中设置类属性是否直接被认为是不好的做法/风格?
答案 0 :(得分:10)
我做对了吗?
是的
在Typescript中设置类属性是否直接视为不良样式?
否。
考虑将状态声明为public readonly
,并使用Readonly modifier。
这将满足TSLint的要求,同时还为您提供了一些保护,以免被错误修改(即不使用this.setState
)。
即使状态仍然暴露在外部,这通常从来都不是问题。
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>
}
}
显式声明访问修饰符是一件好事,即使它隐式导致相同的访问也是如此。它有助于保持代码清晰,因此我不会禁用此TSLint规则。
答案 1 :(得分:0)
我想说,直接设置React组件的public class Undergraduate extends Student
{
private int satScore;
private String classYear;
// ArrayList that maintains a list of valid department names for faculty members
private ArrayList<String> classYearList;
/** The constructor sets initial value for the class year field.
* Explicit call to superclass Employee sets initial values for
* fields firstName, lastName and studentID and gradePointAvg.
* Instantiates and adds classYear to the 'classYearList' ArrayList.
*
* @param firstName Undergraduate Student's first name from indirect superclass Student
* @param lastName Undergraduate Student's last name from indirect superclass Student
* @param gradePointAvg the GPA of the Undegraduate Student
* @param classYear the year of the Undergraduate Student
*/
public Undergraduate(String firstName, String lastName, int studentID, double gradePointAvg, int satScore, String classYear)
{
super(firstName, lastName, studentID, gradePointAvg);
classYearList = new ArrayList<String>();
classYearList.add("FRESHMAN");
classYearList.add("SOPHMORE");
classYearList.add("JUNIOR");
classYearList.add("SENIOR");
setClassYear(classYear);
setSatScore(satScore);
}
/**
* Sets the sat score of the Undergraduates.
* This sat Score must be between 600 and 2400 , or zero (0) meaning sat score not set.
*
* @param satScore sat Score range of Undergraduates
*/
public void setSatScore(int satScore)
{
if ( (satScore >= 600 && satScore <= 2400) || satScore ==0)
{
this.satScore = satScore;
}
}
/**
* Sets the degree earned as either Feshman, Sophmore, Junior, Senior.
*
* @param class year of the Undergraduates
*/
public void setClassYear(String classYear)
{
if (classYear.indexOf(classYear) >=0)
{
this.classYear = classYear;
}
}
/**Returns current value of the satScore field.
*
*@return satsores of students as data type int.
*/
public int getSatScore()
{
return satScore;
}
/**Returns current value of the classYear field.
*
* @return class year of of students as data type String.
*/
public String getClassYear()
{
return classYear;
}
/** Returns fields satScore and classYear fields
* including labels.
*
* @return Formatted sat score and class year fields as type String
*/
public String toString()
{
return super.toString() + "\nSat Score: " + getSatScore()
+ "\nClass Year: " + getClassYear();
}
}
属性是一种不好的做法,除非您将类型注释为与{{1}的状态类型参数相同的类型,除非 }。如果没有注释,TypeScript将从初始值设定项中确定state
的类型,从超类(基于状态类型参数)覆盖该类型,并且如果初始值设定项的类型出现则不会给您错误成为type参数的子类型。稍后可能导致不健全或意外行为;有关示例,请参见this thread。
答案 2 :(得分:0)
状态是不可变的。推荐的设置初始状态的方法是通过构造函数。
请注意,“状态”已经定义并继承,因此无需重新声明:
interface AppState {
charge : number;
spin : number;
color : string;
}
interface AppProps {}
class App extends React.Component<AppProps, AppState> {
constructor(props) {
super(props);
this.state={ charge: 0, spin: -0.5, color:'red' };
}
}
顺便说一句,这正是在react documentations中定义的方式:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
...