如何隔离React Props / State中的更改

时间:2016-09-19 10:01:26

标签: mongodb meteor reactjs

在Meteor / React的上下文中,我有一个订阅Mongo数据库的表组件,这个订阅有一个可以通过props更新的限制参数。我不确定为什么,但似乎componentDidMount生命周期功能几乎不断激发导致令人不快的闪烁。

代码相当冗长,但我附上了我认为有问题的部分 - 更一般地说,你如何去隔离状态/道具的哪些变化导致重新渲染?我已经尝试过监控Chrome工具,但看不到任何变化。

任何反馈或帮助表示赞赏!

import React from 'react';
import booksSingleLine from '../booksTable/booksSingleLine';
import TrackerReact from 'meteor/ultimatejs:tracker-react';


export default class booksListingTable extends TrackerReact(React.Component) {

constructor(props) {
super(props);
console.log("Constructor props are" + this.props.LimitProp);
}

componentWillMount() {
console.log("Mounting booksListingTable");
console.log("Will mount props are" + this.props.LimitProp);
this.state =   {
}
}

componentDidMount(props){
// console.log("Did mount and props are" +props.LimitProp);
var limit = this.props.LimitProp
limit = parseInt(limit) || 5;
this.state =   {
subscription: {
booksData: Meteor.subscribe("allbooks",{sort: {_id:-1}, limit: limit})
}
}
}

componentWillReceiveProps(props) {
  console.log("component will get new props " + props.LimitProp);
// Note that for this lifecycle function we have to reference the props not this.props
  // console.log("component will get weird props " + this.props.LimitProp);
  var limit = props.LimitProp
  limit = parseInt(limit) || 5;
  this.state =   {
  subscription: {
  booksData: Meteor.subscribe("allbooks", {limit: limit})
  }
  }
}

componentWillUnmount() {

}

booksDataLoad(){
var filteredCity = this.props.FilterProp;
console.log("filter is " + filteredCity);
if (filteredCity) {
console.log("just passing a few things")
return (
  remotebookss.find({location: filteredCity}).fetch()
)
}
else {
console.log("passing everything to table");
return(
remotebookss.find().fetch()
)}}

render() {
return(
  <div>
    <table className="ui celled table">
    <thead>
      <tr>
      <th onClick ={this.props.HeaderOnClick}>Name</th>
      <th>Date</th>
      <th>Summary</th>
      <th>Site address</th>
      <th>Price is</th>
    </tr></thead>
<tbody>
{this.booksDataLoad().map( (booksData)=> {
return <booksSingleLine key={booksData._id} booksData={booksData} />
})}
    </tbody>
    <tfoot>
      <tr><th colspan="3">
        <div class="ui right floated pagination menu">
          <a class="icon item">
            <i class="left chevron icon"></i>
          </a>
          <a class="item" onClick= {this.props.methodLoadMore}>Load More</a>
          <a class="icon item">
            <i class="right chevron icon"></i>
          </a>
        </div>
      </th>
    </tr></tfoot>
  </table>
</div>
)
}
}

1 个答案:

答案 0 :(得分:1)

我强烈建议您阅读以下博客文章 -    https://www.discovermeteor.com/blog/data-loading-react/

我看到的事情:

  1. 你在整个地方重置状态
  2. 您并未将订阅作为明确对象进行管理 - 您的代码会泄露它们(FYI)。
  3. 这是一个使用道具和默认道具来设置限制的版本,它只在启动时检查并更改以更改订阅。

    import React from 'react';
    import booksSingleLine from '../booksTable/booksSingleLine';
    import TrackerReact from 'meteor/ultimatejs:tracker-react';
    
    
    export default class booksListingTable extends TrackerReact(React.Component) {
        static propTypes = {
            LimitProp: React.PropTypes.number,
        }
    
        static defaultProps = {
            LimitProp: 5,
        }
    
        constructor() {
            super();
            console.log("Constructor props are" + this.props.LimitProp);
    
            const subscription = Meteor.subscribe("allbooks",{sort: {_id:-1}, limit: this.props.LimitProp})
            this.state = {
                booksData: subscription,
            }
        }
    
        componentWillReceiveProps(nextProps) {
            console.log("component will get new props " + nextProps.LimitProp);
    
            // Start new subscription - if it's changed
            if (this.props.LimitProp != nextProps.limitProp) {
                // Stop old subscription
                this.state.booksData.stop()
                // Setup new subscription
                const subscription = Meteor.subscribe("allbooks",{sort: {_id:-1}, limit: nextProps.LimitProp})
                this.setState({ booksData: subscription })
            }
        }
    
        componentWillUnmount() {
            // Stop old subscription
            this.state.booksData.stop()
        }
    
        booksDataLoad(){
            var filteredCity = this.props.FilterProp;
            console.log("filter is " + filteredCity);
            if (filteredCity) {
                console.log("just passing a few things")
                return (
                  remotebookss.find({location: filteredCity}).fetch()
                )
            }
            else {
                console.log("passing everything to table");
                return(
                    remotebookss.find().fetch()
                )
            }
        }
    
        render() {
            return(
                  <div>
                    <table className="ui celled table">
                    <thead>
                      <tr>
                      <th onClick ={this.props.HeaderOnClick}>Name</th>
                      <th>Date</th>
                      <th>Summary</th>
                      <th>Site address</th>
                      <th>Price is</th>
                    </tr></thead>
                <tbody>
                {this.booksDataLoad().map( (booksData)=> {
                        return <booksSingleLine key={booksData._id} booksData={booksData} /> 
                    })
                }
                    </tbody>
                    <tfoot>
                      <tr><th colspan="3">
                        <div class="ui right floated pagination menu">
                          <a class="icon item">
                            <i class="left chevron icon"></i>
                          </a>
                          <a class="item" onClick= {this.props.methodLoadMore}>Load More</a>
                          <a class="icon item">
                            <i class="right chevron icon"></i>
                          </a>
                        </div>
                      </th>
                    </tr></tfoot>
                  </table>
                </div>
            )
        }
    }