Reputation: 1997
I have a Meteor subscription with some settings, so that I do not publish my whole collection server side. The subscription will be fetched within a createContainer()
from meteor/react-meteor-data
and displayed in a simple <ul>
list, where I also added the document.id to the <li>
element as a key.
Unfortunately as soon as I increase the settings.limit in the subscription 2nd subscription argument (Meteor.subscripte('Collections', settings.limit
) the whole <ul>
list rerenders? What can I do to increase the publication limit, while only adding the new list elements?
P.S. When I publish the total Collection and change the limit in my client via Collection.find({}, {limit: newLimit}).fetch()
, react is working as expected: leaving the old elements as they are and just adding the new ones!
Client Side
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);
Server Side
Meteor.publish('Locations', function(settings) {
return Locations.find({}, {limit: settings.limit, sort: { name: 1} } );
});
The Collection.find().fetch() response
[
{
"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"
}
]
Upvotes: 0
Views: 230
Reputation: 2184
The problem is in your server side logic.
Your current code:
Meteor.publish('Locations', function(settings) {
return Locations.find({}, {limit: settings.limit, sort: { name: 1} } );
});
This will send n number of doc, basically you are 10, 20, 30 and so on docs to the client.
Fix : You need to skip the previous doc.
Solution:
Meteor.publish('Locations', function(settings) {
return Locations.find({}, {skip: settings.skip, limit: settings.limit, sort: { name: 1} } );
});
Or
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} } );
});
Upvotes: 1
Reputation: 1997
Ok I finally found the Problem:
The every time the limit changes the createContainer()
subscribes again to the published collection! Meaning that it sends new props to my Content component, which triggers a rerender! For the short moment it takes to resubscribe the location array, which is saved as a prop, will be overridden by an empty array, which one only notes as a flash in the screen. So for a short second there will be no content displayed and then the new props with the correct locations array is transmitted.
The solutions now to concat()
the new location array into the state of the Content component via componentWillReceiveProps(nextProps)
whenever there are new locations to add. Then one can compare the old and new state, within the shouldComponentUpdate(nextProps, nextState)
and only update when the state is changing!
Upvotes: 0