应该在哪里定义状态?

时间:2019-01-12 15:36:54

标签: reactjs typescript state typescript3.0

这两种在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

那是为什么?

2 个答案:

答案 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,并且如果您不使用类成员箭头表示法,则仅将构造函数用于绑定方法首先。