【问题标题】:States in React, how to preserve the original`?React 中的状态,如何保存原始的`?
【发布时间】:2019-08-24 17:08:39
【问题描述】:

我在一个 SP 框架应用程序中工作,该应用程序从列表中读取、分组和过滤数据。

为此,我在应用程序中有一个从 onclick 事件处理程序调用的方法。

此方法仅包含一个开关,用于检查需要调用的其他方法。它看起来像这样:

private _handleRequest(request: string): void {
switch (request) {
  case 'Customer':
  case 'Sales Manager':
    this.groupHandler(request);
    break;
  case 'Agreement Ended':
    this.getEnded();
    break;
  case 'Last Price Adjustment':
    this.getPassed();
    break;
  default:
    break;
}

}

groupHandler 方法向 Sharepoint 发送一个请求,该请求获取所有数据,然后将数据发送到 ListView 组件,该组件将其呈现在屏幕上:

private groupHandler(group: string): void {
group = group.replace(/ +/g, "");
this.setState({
  groupByFields: [{
    name: group,
    order: GroupOrder.ascending
  }]
});

} }

getEnded 和 getPassed 几乎相似,都是从 sharepoint 获取数据并在将结果发送到 ListView 组件之前对其进行过滤。 每个方法更新状态:

private getEnded(): void {

this.props.provider.getEnded().then((listItems: IList[]) => {
  this.setState({
    listItems: listItems
  });
});

}

私有 getPassed(): 无效 {

this.props.provider.getPassed().then((listItems: IList[]) => {
  this.setState({
    listItems: listItems
  });
});

}

它是这样初始化的:

export interface IListState {

listItems: IList[]; }

导出默认类 AgreementDatabase 扩展 React.Component { 构造函数(道具:IAgreementDatabaseProps){ 超级(道具);

this.state = {
  listItems: []
};


this.groupHandler = this.groupHandler.bind(this);

}

这是我使用从 SharePoin 列表中获取的数据填充状态的 componentDidMount:

public componentDidMount(): void {
this.props.provider.getContent().then((listItems: IList[]) => {
  this.setState({
    listItems: listItems
  });
});

}

现在的问题是,当我运行应用程序并单击调用 groupHandler 方法的链接时,列表会毫无问题地分组。当列表分组后,我单击调用 getEnded 或 getPassed 方法的链接时会出现问题。在这种情况下,列表不会在过滤结果之前重新加载。我得到的是一个带有过滤结果的分组列表。 我发布了一些图片以便更好地理解。

如何重置状态,以便每次单击按钮时,应用都会在应用过滤或分组之前获取原始状态/值?

最好的问候 美国

【问题讨论】:

  • 嗯..我不完全明白:您的组件在安装时获取数据,然后您只想根据您单击的按钮过滤该数据?我不明白您在哪里检索第一张图片中显示的数据
  • 我在 componentDidMount() 中获取的数据。在那里,我调用了一个方法,其中包含将请求发送到 SharePoint 列表并使用获取的数据填充状态的代码。我用那个 componentDidMount 代码更新了帖子。
  • 好的,我猜对了,然后:) 最后一个我需要回答的问题:使用groupHandler()getEnded()getPassed(),您只想过滤您想要的项目'已经在componentDidMount() 中取得了,对吧?您不获取任何新项目,您只是“隐藏”一些已经获取的项目。我对么?如果是这样,我可以给你一个例子来说明如何实现你想要的
  • 关于 getEnded 和 getPassed 我想过滤(隐藏结果)不符合条件的,例如:如果结束协议日期早于今天。为了获得该值,我正在使用该过滤器向共享点发送一个新的休息请求。现在如果有更好的方法,那就太好了。目前只有两种向 SP 发送请求的方法,但还可以更多。
  • 嗯,我想更多的是改变render() 函数。我看不出来,但是..让我添加一个答案(这里写得太长了)

标签: reactjs state spfx


【解决方案1】:

我认为我找到了真正的问题,它与状态无关。 在渲染方法中,我使用 ListView 来渲染列表,在这个组件中,我使用 groupByFields 属性来自动对结果进行分组:

<ListView
        items={this.state.listItems}
        viewFields={this._viewFields}
        groupByFields={this.state.groupByFields}
      />

这些组来自 groupByFields 状态。

我真正需要做的是在我想要过滤时找到停用此 groupByfield 属性的方法,否则无论我如何过滤或操作状态,结果都会被分组。

你知道怎么做吗?或仅在以下情况下添加此属性的方法 groupHandler 方法被调用了吗?

最好的问候 美国

【讨论】:

    【解决方案2】:

    我认为我找到了真正的问题,它与状态无关。 在渲染方法中,我使用 ListView 来渲染列表,在这个组件中,我使用 groupByFields 属性来自动对结果进行分组:

    <ListView
            items={this.state.listItems}
            viewFields={this._viewFields}
            groupByFields={this.state.groupByFields}
          />
    

    这些组来自 groupByFields 状态。

    我真正需要做的是在我想要过滤时找到停用此 groupByfield 属性的方法,否则无论我如何过滤或操作状态,结果都会被分组。

    你知道怎么做吗?还是仅在调用 groupHandler 方法时添加此属性的方法?

    编辑:我找到了这个解决方案: 我调用了一个叫做 renderList 的方法:

    private _renderList(): any {
    if (this.state.filter) {
      return ( <ListView
                items={this.state.filteredListItems}
                viewFields={this._viewFields}
              />)
    } else {
      return (<ListView
                items={this.state.originalitems}
                viewFields={this._viewFields}
                groupByFields={this.state.groupByFields}
              />)
    }
    

    }

    我使用状态来查看是否应该呈现过滤器或分组列表

    感谢您抽出宝贵时间,这有助于 med 跳出框框思考

    最好的问候 美国

    【讨论】:

      【解决方案3】:

      所以,我的想法是将filter 保留在状态中,该属性在getPassed()getEnded() 方法中设置。
      比如getPassed(),你设置filter = "passed";相反,在getEnded() 中设置filter = "ended"。最后,默认情况下,filter 属性可以设置为null

      然后,写这样的东西:

      /* Inside your Component */
      renderPassed = () => {
        const itemToRender = [];
      
        this.state.listItems.forEach(item => {
          if (item.status === "passed") {
            itemToRender.push(item);
          }
        }
      
        return itemToRender;
      }
      
      renderEnded = () => {
        const itemToRender = [];
      
        this.state.listItems.forEach(item => {
          if (item.status === "ended") {
            itemToRender.push(item);
          }
        }
      
        return itemToRender;
      }
      
      render() {
        let itemToRender;
      
        switch (this.state.filter) {
          case "passed": itemToRender = this.renderPassed(); break;
          case "ended": itemToRender = this.renderEnded(); break;
          default: itemToRender = this.state.listItems;
        }
      
        return <div>{itemToRender}</div>;
      }
      

      这确实是一种简化,但我认为您可以理解我的想法。
      我不知道你是否知道一个项目是否通过和/或结束,我只是假设每个项目都有一个 status 属性。

      有帮助吗?可以在你的 App 中实现吗?

      编辑:请注意,我没有“重置”状态。它没有用,因为您有两种选择:

      1. 再次执行获取;

      2. 将原始数据保存到类的属性中,但是您会在原始数据和过滤数据中重复一些项目;

      【讨论】:

      • 我会尝试一下并与 cmets 一起回归。非常感谢!!
      • 我添加了答案!
      猜你喜欢
      • 1970-01-01
      • 2015-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      • 2020-09-15
      相关资源
      最近更新 更多