代码之家  ›  专栏  ›  技术社区  ›  Mevia

设置管理大量记录时的长执行状态

  •  0
  • Mevia  · 技术社区  · 6 年前

    我正在尝试解决react应用程序中出现的问题。在其中一个视图(组件)中,我有一个操作大数据的管理工具。基本上当视图加载时 componentDidMount 这将触发ajax fetch,下载由大约50000条记录填充的数组。每个数组行是一个有8-10个键值对的对象。

    import React, { Component } from "react";
    import { List } from "react-virtualized";
    import Select from "react-select";
    
    class Market extends Component {
      state = {
        sports: [], // ~ 100 items
        settlements: [], // ~ 50k items
        selected: {
          sport: null,
          settlement: null
        }
      };
    
      componentDidMount() {
        this.getSports();
        this.getSettlements();
      }
    
      getSports = async () => {
        let response = await Ajax.get(API.sports);
    
        if (response === undefined) {
          return false;
        }
    
        this.setState({ sports: response.data });
      };
    
      getSettlements = async () => {
        let response = await Ajax.get(API.settlements);
    
        if (response === undefined) {
          return false;
        }
    
        this.setState({ settlements: response.data });
      };
    
      save = (key, option) => {
        let selected = { ...this.state.selected };
        selected[key] = option;
        this.setState({ selected });
      };
    
      virtualizedMenu = props => {
        const rows = props.children;
        const rowRenderer = ({ key, index, isScrolling, isVisible, style }) => (
          <div key={key} style={style}>
            {rows[index]}
          </div>
        );
    
        return (
          <List
            style={{ width: "100%" }}
            width={300}
            height={300}
            rowHeight={30}
            rowCount={rows.length || 1}
            rowRenderer={rowRenderer}
          />
        );
      };
    
      render() {
        const MenuList = this.virtualizedMenu;
    
        return (
          <div>
            <Select
              value={this.state.selected.sport}
              options={this.state.sports.map(option => {
                return {
                  value: option.id,
                  label: option.name
                };
              })}
              onChange={option => this.save("sport", option)}
            />
            <Select
              components={{ MenuList }}
              value={this.state.selected.settlement}
              options={this.state.settlements.map(option => {
                return {
                  value: option.id,
                  label: option.name
                };
              })}
              onChange={option => this.save("settlement", option)}
            />
          </div>
        );
      }
    }
    

    我遇到的问题是,在下载大数据并保存到视图状态之后,即使我想使用select更新值,它有大约100条记录,也需要几秒钟的时间。例如想象一下 smallData 100件物品的排列 { id: n, name: 'xyz' } selectedFromSmallData 只是数据数组中的单个项,用html select选择。

    在大数据加载之前进行选择 ms ,但数据加载并保存到状态后,突然需要2-4秒。

    有什么可能有助于解决这个问题(不幸的是,我不能对这些数据进行分页,这不是我可以访问的任何东西)。

    0 回复  |  直到 6 年前
        1
  •  1
  •   UjinT34    6 年前

    .map() 在每个渲染上创建一个新数组。为了避免这种情况,您有三种选择:

    1. 商店 state.sports state.settlements 已经准备好了 Select
    2. 每次你换衣服 体育运动 州和解 也改变 state.sportsOptions state.settlementsOptions
    3. 使用 componentDidUpdate 更新 state.*Options :

    第三种选择可能更容易实现。但它将触发另一个重发:

      componentDidUpdate(prevProps, prevState) {
        if (prevState.sports !== this.state.sports) {
          this.setState(oldState => ({sportsOptions: oldState.sports.map(...)}));
        }
        ...
      }
    

    你的 onChange 处理程序将在每次呈现时重新创建,并可能触发不必要的 选择 . 创建两个单独的方法以避免:

    saveSports = option => this.save("sport", option)
    ...
    render() {
      ...
      <Select onChange={this.saveSports}/>
      ...
    }
    

    你也有类似的问题 components={{ MenuList }} . 将其移到状态或构造函数中,以便 {MenuList} 对象只创建一次。你应该这样做:

        <Select
          components={this.MenuList}
          value={this.state.selected.settlement}
          options={this.state.settlementsOptions}
          onChange={this.saveSettlements}
        />
    

    如果这无助于考虑使用默认值 select 并使用 PureComponent 以呈现其选项。或者尝试使用 custom PureComponents 渲染 选择 .

    也检查 React-select is slow when you have more than 1000 items

        2
  •  0
  •   Mihályi Zoltán    6 年前

    数组的大小应该不成问题,因为只有引用存储在state对象中,而react在state上没有做任何深度相等的操作。 可能您的render或componentDidUpdate在这个大数组上迭代,这会导致问题。 如果这没有帮助,请尝试分析你的应用程序。