gpt4 book ai didi

reactjs - 为什么 null React 组件状态初始化得到的是 `never` 类型?

转载 作者:搜寻专家 更新时间:2023-10-30 20:38:50 25 4
gpt4 key购买 nike

当在组件的构造函数之外将组件的状态初始化为 null 时,状态在渲染函数中的类型为 never

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

根据 StackOverflow 上关于这两种初始化状态(在 babeled JS 中)的大多数问题,这两种方法应该是等价的。但是,在 Typescript 中,它们不是。这是错误还是预期的行为?

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

这是 CodeSandbox 上的示例代码:https://codesandbox.io/s/10l73o4o9q

最佳答案

According to most questions on StackOverflow about the two ways to initialize state (in babeled JS), these two methods should be equivalent. However, in Typescript, they are not.

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

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

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

您可以看到 state 的类型是{selected: null} , 正如预期的那样。变成never在这段代码中

const { selected } = this.state;
let selectedLabel = <div>None selected</div>;
if (selected) {

因为里面if语句,selected 的类型缩小范围,使用 selected 的信息是true . Null 永远不可能为真,因此类型变为 never .

按照其他答案中的建议,您可以注释 State在类主体中初始化时显式

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

更新以阐明类体中的初始化与构造函数中的赋值有何不同

当您设置 state 时在构造函数中

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

您正在将值分配给 state在基类中声明时已经存在的属性。基类是React.Component<Props, State> , 和 state 声明那里的属性(property)有State类型,取自 <Props, State> 中的第二个通用参数.

赋值不会改变属性的类型 - 它仍然是 State ,无论分配的值如何。

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

关于reactjs - 为什么 null React 组件状态初始化得到的是 `never` 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51201315/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com