Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 为什么null React组件状态初始化得到'never'类型?_Reactjs_Typescript - Fatal编程技术网

Reactjs 为什么null React组件状态初始化得到'never'类型?

Reactjs 为什么null React组件状态初始化得到'never'类型?,reactjs,typescript,Reactjs,Typescript,在组件构造函数外部将组件状态初始化为null时,该状态在渲染函数中具有类型never 但是,当在构造函数中初始化状态时,状态具有正确的类型 根据有关StackOverflow的大多数问题,关于初始化状态的两种方法(在babeled JS中),这两种方法应该是等效的。然而,在Typescript中,它们不是。这是一个bug还是预期的行为 import * as React from "react"; import * as ReactDOM from "react-dom"; interface

在组件构造函数外部将组件状态初始化为
null
时,该状态在渲染函数中具有类型
never

但是,当在构造函数中初始化状态时,状态具有正确的类型

根据有关StackOverflow的大多数问题,关于初始化状态的两种方法(在babeled JS中),这两种方法应该是等效的。然而,在Typescript中,它们不是。这是一个bug还是预期的行为

import * as React from "react";
import * as ReactDOM from "react-dom";

interface Person {
  name: string;
  address: string;
}
interface Props {
  items: Person[];
}
interface State {
  selected: Person | null;
}

class PersonSelector extends React.Component<Props, State> {
  // DOES NOT WORK:
  state = {
    selected: null
  };

  constructor(props: Props) {
    super(props);
    // WORKS:
    // this.state = {
    //   selected: null
    // };
  }

  handleClick = (item: Person) => {
    this.setState({
      selected: item
    });
  };

  render() {
    const { selected } = this.state;
    let selectedLabel = <div>None selected</div>;
    if (selected) {
      selectedLabel = <div>You selected {selected.name}</div>;
    }
    return (
      <div>
        {selectedLabel}
        <hr />
        {this.props.items.map(item => (
          <div onClick={() => this.handleClick(item)}>{item.name}</div>
        ))}
      </div>
    );
  }
}

const people: Person[] = [
  { name: "asdf", address: "asdf asdf" },
  { name: "asdf2", address: "asdf asdf2" }
];

document.write('<div id="root"></div>');
ReactDOM.render(
  <PersonSelector items={people} />,
  document.getElementById("root")
);
import*as React from“React”;
从“react dom”导入*作为react dom;
接口人{
名称:字符串;
地址:字符串;
}
界面道具{
项目:人[];
}
界面状态{
选中:人员|空;
}
类PersonSelector扩展React.Component{
//不起作用:
状态={
所选:空
};
建造师(道具:道具){
超级(道具);
//作品:
//此.state={
//所选:空
// };
}
handleClick=(项目:人)=>{
这是我的国家({
选定:项目
});
};
render(){
const{selected}=this.state;
让selectedLabel=未选择;
如果(选定){
selectedLabel=您选择了{selected.name};
}
返回(
{selectedLabel}

{this.props.items.map(item=>( this.handleClick(item)}>{item.name} ))} ); } } const people:Person[]=[ {名称:“asdf”,地址:“asdf asdf”}, {名称:“asdf2”,地址:“asdf asdf2”} ]; 文件。写(“”); ReactDOM.render( , document.getElementById(“根”) );

下面是CodeSandbox上的示例代码:

您完全可以在构造函数之外初始化状态,但需要确保键入它,以便TypeScript可以协调初始值的类型和泛型的类型。尝试:

class PersonSelector extends React.Component<Props, State> {
    state: State = {
        selected: null
    };

    // ...
}
类PersonSelector扩展React.Component{
状态:状态={
所选:空
};
// ...
}
根据大多数关于StackOverflow的问题,有两种方法 初始化状态(在babeled JS中),这两个方法应该是 相等的然而,在Typescript中,它们不是


它们在类型脚本中是不同的,因为在类主体(而不是构造函数)中分配
状态
PersonSelector
中声明
状态
,覆盖基类
React.Component
中的声明。在TypeScript中,重写声明允许具有与基类中相同属性的类型单向兼容的不同、更严格的类型

在没有类型注释的情况下初始化时,此类型由值的类型确定:

class PersonSelector extends React.Component<Props, State> {
  // DOES NOT WORK:
  state = {
    selected: null
  };
因为在
if
语句中,使用
selected
true
的信息,所选
的类型被缩小。Null永远不能为true,因此类型变为

正如在另一个答案中所建议的,当在类主体中初始化时,可以显式地注释
状态

class PersonSelector extends React.Component<Props, State> {
  state: State = {
    selected: null
  };
您正在将该值赋值给已存在的
state
属性,因为它是在基类中声明的。基类是
React.Component
,其中的属性声明为具有
State
类型,取自
中的第二个泛型参数

指定不会更改属性的类型-无论指定的值是什么,它都保持
状态


当您在类主体中设置
state
时,它不仅仅是赋值-它是类属性的声明,并且每个声明都为声明的实体提供一个类型-可以通过类型注释显式地,也可以隐式地从初始值推断。即使基类中已经存在属性,也会发生这种类型化。我在文档中找不到任何东西可以证实这一点,但有一个文档准确地描述了这种行为,并确认有时它违背了开发人员的意图(到目前为止还没有用这种语言实现的解决方案)。

谢谢您的回答!我仍然不太确定我是否理解“在没有类型注释的情况下初始化时,此类型是根据值的类型确定的”。为什么在构造函数中设置
this.state
时不正确?这是由于typescript中固有的限制,还是能够用class属性限制
状态的类型是一种期望的行为?“它们在typescript中是不同的,因为类主体(而不是构造函数)中的赋值状态在PersonSelector中声明状态,覆盖基类React.Component中的声明”. 在typescript文档中有没有一个地方可以让我阅读更多关于这种差异的信息?@Eric我更新了答案。我发现唯一能证实这一点的是,谢谢!github的问题正是我想要的。
class PersonSelector extends React.Component<Props, State> {
  state: State = {
    selected: null
  };
  constructor(props: Props) {
    super(props);
    this.state = {
       selected: null
    };
  }