简体   繁体   English

应该在哪里定义状态?

[英]Where should a state be defined?

What is the difference between these two constructs of defining state in React? 这两个在React中定义状态的构造之间有什么区别?

class ProductsPage extends Component {
  constructor(props) {
    super(props);
    this.state = {
      products: []
    };
  }
  ...
}

and this: 和这个:

class ProductsPage extends Component {
  state = {
    products: []
  };
  ...
}

Both of them work well when coded in ES6. 当用ES6编码时,它们都可以很好地工作。 However, the lower one doesn't seem to work in typescript 3. I have the following: 但是,较低的版本似乎不适用于打字稿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>
    );
  }
}

and the ts compiler flagged an error saying: Property id does not exist on type 'never' ts编译器标记了一个错误,说:“ never”类型不存在属性ID

Why is that? 这是为什么?

The second form is class properties which is a stage 3 JavaScript proposal (meaning it's not part of the language yet). 第二种形式是类属性 ,它是第3阶段JavaScript提议(意味着它还不是语言的一部分)。 Adding properties on the constructor is the old ES2015 way (called maximally minimal classes). 在构造函数上添加属性是旧的ES2015方法 (称为最大最小类)。

In your case there is no functional difference. 就您而言,没有功能上的差异。

TypeScript requires you to declare class fields for type safety - hence the warning. TypeScript要求您声明类字段以确保类型安全-因此发出警告。

How to define the state for a React component is as subjective as the coding styles React promotes itself. 如何定义React组件的状态与React本身所倡导的编码风格一样主观。 Usually I go the very strict route which looks as follows: 通常我会走非常严格的路线,如下所示:

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 });
    }
}

As you can see, I explicitly mark state as readonly just make sure, nobody attempts to write directly to it (even though IDEs and linters can check for those errors without the precaution nowadays). 如您所见,我确保将state显式标记为只读,只是要确保没有人尝试直接写入状态(即使如今IDE和linter都可以检查这些错误而无需采取任何预防措施)。

Another reason why I prefer to not set the state manually with an assigment is that it might encourage wrong handling of state. 我宁愿不随便手动设置状态的另一个原因是,它可能会鼓励错误地处理状态。 You are never to assign something directly to state in a class method without the use of setState . 在没有使用setState情况下,永远不要在类方法中直接为state赋值。

Furthermore I am basically defining the defaults right away and populating the state with dynamic data in componentDidMount . 此外,我基本上是立即定义默认值,并在componentDidMount中用动态数据填充状态。 This approach allows you to keep the code concise by dropping an explicit constructor definition as you should move such an initialization to componentDidMount anyways and use the constructor only for binding methods if you don't use the class member arrow notation for those in the first place. 这种方法允许您通过删除一个显式的构造函数定义来保持代码简洁,因为无论如何您都应将此类初始化移动到componentDidMount并且如果您不首先使用类成员箭头表示法,则仅将构造函数用于绑定方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM