组件渲染混乱

时间:2019-05-08 14:50:58

标签: javascript reactjs underscore.js

我正在使用React&_underscorejs从JSON对象数组中过滤单个数据元素,并将其呈现在表中的屏幕上。我的代码将呈现已过滤的数据,但是几秒钟后,整个表也将呈现。

  this.state = { stats:[],
  value:'';

  componentDidMount() {
   fetch('http://localhost:5000/cityStats')
  .then((data) => data.json())
  .then((data) => this.setState( { stats: data } ))
  ;
  }
  // Using a select menu to select value
  handleChange = (e) => {
  this.setState({ value: e.target.value });

  // Filtering a element that matches  value choosen
  this.setState( { "stats": _.where(this.state.stats, 
  {NAME:e.target.value})});
   this.getDataAgain();
  }
  // 
  getDataAgain (){
  fetch('http://localhost:5000/citystats')
  .then((data) => data.json())
  .then((data) => this.setState( { stats: data } ));
  }

如果我不调用getDataAgain(),则过滤器将只工作一次并显示空白列表。当用户选择一个选项时,如何解决它以仅显示过滤的数据?

2 个答案:

答案 0 :(得分:1)

使用两个数组并调用一次端点,将原始数组保存在两个数组this.setState({ stats: data, filtered: data})中。使用filtered数组作为数据源。

state = { stats: [], filtered: [], value: '' };

componentDidMount = () => {
  this.getDataAgain();
}
// Using a select menu to select value
handleChange = e => {
  this.setState({ value: e.target.value });

  // Filtering a element that matches  value choosen
  const filtered = _.where(this.state.stats, { NAME: e.target.value });
  this.setState({
    filtered: filtered
  });
};
//
getDataAgain = () => {
  fetch('http://localhost:5000/citystats')
    .then(data => data.json())
    .then(data => this.setState({ stats: data, filtered: data }));
}

您当前正在使用stats的地方,将其更改为this.state.filtered

答案 1 :(得分:0)

这里的主要问题是您正在使用过滤的对象覆盖数据。这绝对是解决该问题的错误方法。将数据设置为状态后,就不应对其进行突变,以避免其他不必要的api请求。

注意:此外,您还应该删除getDataAgain或将其命名为getData,然后在CDM方法中对其进行调用,以避免代码重复。

componentDidMount() {
   this.getData();
}

getData() {
  fetch('http://localhost:5000/cityStats')
  .then((data) => data.json())
  .then((stats) => this.setState( { stats } ))  
}

方法1:使用私有属性设置/取消设置数据

  stats = undefined; // Will permanently hold the whole dataset

  componentDidMount() {
    fetch('http://localhost:5000/cityStats')
      .then(data => data.json())
      .then(stats => {
        this.stats = stats; // Saves the whole unfiltered dataset to private prop
        this.setState({ stats });
      });
  }

  handleChange = e => {
    const { value } = e.target.value;

    // In case value is unset it will revert stats to the whole unfiltered set 
    // from the data prop
    this.setState({
      value,
      stats: value ? _.where(this.state.stats, { NAME: value }) : this.stats
    });
  };

方法2:在渲染中进行过滤(可选的存储方式)

只需在渲染中对其进行过滤。如果您没有庞大的数据集,则不会造成任何性能问题。

  render() {
    const { stats, value } = this.state;
    const filteredData = value
      ? _.where(stats, { NAME: value })
      : stats;

    .. do something with filteredData
  }

即使在数据集很大的情况下,也应该在render函数中进行过滤,因此始终显示正确过滤的数据。唯一的区别是,在这种情况下,您将使用某种形式的记忆功能,以便每个过滤的集都被缓存以备下一次渲染。

一个基本示例:https://medium.com/@planttheidea/memoize-react-components-33377d7ebb6c