这两种在React中定义状态的构造有什么区别?
class ProductsPage extends Component {
constructor(props) {
super(props);
this.state = {
products: []
};
}
...
}
这:
class ProductsPage extends Component {
state = {
products: []
};
...
}
在ES6中进行编码后,它们两者都可以很好地工作。但是,较低的版本似乎不适用于打字稿3。我有以下内容:
interface IState {
products: IProduct[];
}
class ProductsPage extends Component<{}, IState> {
state = {
products: []
};
public componentDidMount() {
this.setState({ products });
}
public render() {
return (
<div className="page-container">
<ul className="product-list">
{this.state.products.map(p => (
<li className="product-list-item" key={p.id}>
{p.name}
</li>
))}
</ul>
</div>
);
}
}
并且ts编译器标记了一个错误,指出:类型'never'不存在属性ID
那是为什么?
答案 0 :(得分:1)
第二种形式是class properties,它是第3阶段JavaScript提案(意味着它还不是该语言的一部分)。 old ES2015 way(称为最大最小类)在构造函数上添加属性。
就您而言,没有功能上的区别。
TypeScript要求您声明类字段以确保类型安全-因此发出警告。
答案 1 :(得分:1)
如何定义React组件的状态与React自身的编码风格一样主观。通常我会走非常严格的路线,如下所示:
let dialog = <ProjectDialog/>;
class Home extends Component {
handleCardClick = id => {
dialog.handleOpen();
};
正如您所看到的,我只是明确地将type State = {
someStateVar: number[];
};
export class MyComponent extends Component<{}, State> {
public readonly state: State = {
someStateVar: [],
};
public async componentDidMount() {
// Dynamically fetch data (maybe via axios) and populate the new state
const data = await axios.get<number[]>(...);
this.setState({ someStateVar: data });
}
}
标记为只读,只是要确保没有人试图直接写它(即使如今IDE和linter都可以在没有预防措施的情况下检查这些错误)。
为什么我不想随便手动设置状态的另一个原因是,它可能会鼓励错误地处理状态。在没有使用state
的情况下,您永远不能在类方法中直接将某些内容分配给state
。
此外,我基本上是立即定义默认值,并在setState
中用动态数据填充状态。这种方法使您可以通过删除显式构造函数定义来保持代码简洁,因为无论如何您都应将这样的初始化移动到componentDidMount
,并且如果您不使用类成员箭头表示法,则仅将构造函数用于绑定方法首先。