Meteor + React:Meteor.subscribe('Collection', limit) 触发器重新渲染每个列表元素

Meteor + React: Meteor.subscribe('Collection', limit) Triggers Rerender Every List Element

我有一个带有一些设置的 Meteor 订阅,所以我不会发布我的整个收集服务器端。订阅将从 meteor/react-meteor-data 中的 createContainer() 中获取并显示在一个简单的 <ul> 列表中,我还将 document.id 添加到 <li> 元素作为关键。

不幸的是,一旦我在订阅第二个订阅参数 (Meteor.subscripte('Collections', settings.limit) 中增加 settings.limit,整个 <ul> 列表就会重新呈现?我可以做些什么来增加发布限制,同时只添加新的列表元素?

P.S。当我发布总集合并通过 Collection.find({}, {limit: newLimit}).fetch() 更改我的客户端中的限制时,react 按预期工作:保留旧元素,只添加新元素!


客户端

import React, { Component } from 'react';
import { Locations } from '/both/collections/locations.js';
import { Events } from '/both/collections/events.js';
import { createContainer } from 'meteor/react-meteor-data';

class Content extends React.Component {
  constructor(props) {
    super(props);
    this.renderLocations = this.renderLocations.bind(this);
  }

  renderLocations() {
    return this.props.locations.map(function(location) {
      return (<li key={location._id} >{location.name}</li>);
    });
  }

  render() {
    console.log(this.props);
    return !this.props.loading && (
      <div>
    <ul>
      {this.renderLocations()}
    </ul>
      <h1 onClick={this.props.increaseLimit}> Limit </h1>
      <div style={{marginBottom: "100px"}}></div>
      </div>
    );
  }
}

export default createContainer((props) => {
  const settings = {
    limit: props.limit,
  }
  const locationsSubscribe = Meteor.subscribe('Locations', settings);
  const loading = !locationsSubscribe.ready();
  if(loading) {
    return { loading };
  } else {
    const _locations = Locations.find({}, {fields: { name: 1}, sort: { name: 1 }}).fetch();

    return {
      loading, 
      locations: _locations,
      increaseLimit: props.increaseLimit,
    };
  }
}, Content);

服务器端

Meteor.publish('Locations', function(settings) {
  return Locations.find({}, {limit: settings.limit, sort: { name: 1} } );
});

Collection.find().fetch() 响应

[
  {
    "name": "3-Master Bike-Style",
    "_id": "N9rWyZMdxEe6jhNW2"
  },
  {
    "name": "43einhalb",
    "_id": "bPgpBm59LohGLaAsf"
  },
  {
    "name": "A&B Döner",
    "_id": "qTNMk73ThvaPxGWqM"
  },
  {
    "name": "A.T.U ",
    "_id": "aWzSmp2zZ8etDhHk6"
  },
  {
    "name": "AIKO Sushibar - Hot Wok",
    "_id": "9pQJgeBNo5gFRkKdF"
  },
  {
    "name": "AXA Stefan Hahn",
    "_id": "d9f6mTrSTGCoeKPbP"
  }
]

好的,我终于找到了问题所在: 每次限制更改 createContainer() 都会再次订阅已发布的 collection!这意味着它将新道具发送到我的 Content 组件,这会触发重新渲染!在重新订阅保存为 prop 的位置数组所需的短时间内,将被一个空数组覆盖,它只会在屏幕上显示为一闪而过。因此在短时间内不会显示任何内容,然后传输具有正确位置数组的新道具。

解决方案现在 concat() 每当有新位置要添加时,新位置数组就会通过 componentWillReceiveProps(nextProps) 进入 Content 组件的状态。然后可以在 shouldComponentUpdate(nextProps, nextState) 内比较新旧状态,并且仅在状态发生变化时更新!

问题出在您的服务器端逻辑上。

您当前的代码:

Meteor.publish('Locations', function(settings) {
  return Locations.find({}, {limit: settings.limit, sort: { name: 1} } );
});

这会发送n个doc,基本上你是10、20、30等等docs给客户。

Fix : 您需要跳过之前的文档。

解法:

Meteor.publish('Locations', function(settings) {
  return Locations.find({}, {skip: settings.skip, limit: settings.limit, sort: { name: 1} } );
});

或者

Meteor.publish('Locations', function(settings) {
  var skip = settings.pageNumber * settings.number_of_record_per_page; //change variable according to you
  return Locations.find({}, {skip: settings.limit, limit: settings.limit, sort: { name: 1} } );
});