映射函数和React setState

时间:2020-09-03 10:13:33

标签: reactjs typescript

我是React的新手。

我需要更新状态下的对象的属性。 我尝试使用下面的代码并遇到错误。

能请您解释一下我在做什么错。

export interface IResultSourcesListItemsState {
  listitems: [
{
  "Title": string,
  "sourceGuid": string,
  "isChecked": boolean
}
  ]
}

_

public constructor(props: IResultSourcesProps, state: IResultSourcesListItemsState) {
    super(props);
    this.state = {
      listitems: [
        {
          "Title": "",
          "sourceGuid": "",
          "isChecked": true
         }
       ],
     };
     ResultSources.siteUrl = this.props.webSiteUrl;
}

resultSourceValueChange(checked, value) {
    let stateChanged = false;
    const updatedState = this.state.listitems.map((listitem) => {
      if (listitem.Title === "All" && listitem.isChecked) {
        listitem.isChecked = false;
        stateChanged = true;
      }
      return listitem;
    });
    if (stateChanged)
      this.setState({listitems: updatedState});
}

enter image description here

我简化了代码, 现在这段代码可以正常工作了

const updatedState = this.state.listitems;
this.setState({listitems: updatedState});

但是此代码无法编写代码,为什么?

const updatedState = [...this.state.listitems];
this.setState({listitems: updatedState});

2 个答案:

答案 0 :(得分:1)

因此,当您询问IResultSourcesListItemsState的定义时,您会遇到我以为的错误。您的错误与TypeScript有关,与React无关。

使用语法let foo:[string] = ...时,foo是具有单个元素(始终具有单个元素的列表)的元组。例如,let bar:[string, string, string] = ...将始终具有三个元素。如果要定义“普通”列表,则必须使用语法let baz:string[] = ...

由于map的返回值是一个列表,而不是一个元组,并且您所在状态的listitems的类型是一个元组,因此会出现错误。 TypeScript无法保证map的返回将始终只有一个元素,因此类型与您的listitems属性之一不兼容。

要解决此问题,您要按以下方式重新定义界面IResultSourcesListItemsState

export interface IResultSourcesListItemsState {
  listitems: {
     "Title": string,
     "sourceGuid": string,
     "isChecked": boolean
  }[]
}

请注意,这里是在map函数上直接更改状态,这是一个不好的做法:

resultSourceValueChange(checked, value) {
    let stateChanged = false;
    const updatedState = this.state.listitems.map((listitem) => {
      if (listitem.Title === "All" && listitem.isChecked) {
        listitem.isChecked = false;
        stateChanged = true;
      }
      return listitem;
    });
    if (stateChanged)
      this.setState({listitems: updatedState});
}

答案 1 :(得分:0)

最后我解决了我的问题。

我强制添加as any。所以这行是

this.setState({listitems: updatedState} as any);

this.setState({listitems: updatedState} as Pick<IResultSourcesListItemsState, keyof IResultSourcesListItemsState>);

我不知道为什么会这样。 This topic对我有帮助。