kations
December 25, 2017, 1:31pm
1
On Meteor 1.5 and 1.6 withTracker don’t react on prop changes from a higher order Component.
I have a Form Component with a Relations Input Component where I sub to data based on the Form Component State:
The Relations container:
export default RelationContainer = withTracker((props) => {
console.log(props.value);
…
})(Relation);
if I change the state of Form, no console.log gets fired and nothing changes.
hope someone could help
I need more to be able to help you, but i can take a wild guess:
You should put a reactive function in your withTracker function and return that value as part of an object. Reactive values are for example Collection.find() or Meteor.user()
if you want withTracker rerun, you have to provide an reactive source at least.
Session.set('test', Date.now())
const Rerun = withTracker(props => {
console.log(Session.get('test'))
})(() => <div>hello</div>)
open console then
Session.set('test', Date.now())
reactive source
can be
cursor.fetch()
cursor.map()
collection.findOne()
reactive var / dict / session
meteor.userId()
meteor.user()
Meteor.status()
etc …
kations
December 27, 2017, 11:07am
4
It was a bad idea to shorten the code, of course I have some reactive functions in the container:
Complete container code:
export default RelationContainer = withTracker((props) => {
console.log(‘RelationContainer’,props.value);
const realtionIds = props.value ? props.value : [];
const handle = Meteor.subscribe(‘relations’, props.projectId, props.relation, realtionIds);
const loading = !handle.ready();
var relationType = ContentTypes.findOne({slug: props.relation});
return {
relationEntries: relationType ?
ContentEntries.find({_id: {$in: realtionIds}, contentTypeId: relationType._id}).fetch()
: [],
relationType: relationType,
};
})(Relation);
The subscription is based of the container props (Array of Ids), but if the props change no rerun of the container.
The strange thing is that the child Relation component get the new Ids. But the relationEntries prop from the container don’t change.
Thanks for your help
it looks okay const loading = !handle.ready();
if this ‘relations’ subscription did return publish ready or publish stop event throw error,
the loading will rerun with true or false
try log loading first see if it changes value while subscribe.
maybe publish never hit ready or stop with correct record ?
kations
December 30, 2017, 10:20am
6
@crapthings In the first run all work as aspected. Loading is true, than false and the child gets the docs from sub.
But when the Ids Array changed at the Parent component, the Container don’t rerun, but the child Relation component get these new Ids.
For me it seems that the withTracker container don’t react on prop changes from parent components.
Maybe there is a workaround to trigger the update manually, like this.forceUpdate()?
withTracker already did it for u
// We use a brand-new autorun for each call to getMeteorData
// to capture dependencies on any reactive data sources that
// are accessed. The reason we can't use a single autorun
// for the lifetime of the component is that Tracker only
// re-runs autoruns at flush time, while we need to be able to
// re-call getMeteorData synchronously whenever we want, e.g.
// from componentWillUpdate.
c.stop();
// Calling forceUpdate() triggers componentWillUpdate which
// recalculates getMeteorData() and re-renders the component.
component.forceUpdate();
}
})
));
if (Package.mongo && Package.mongo.Mongo) {
Object.keys(data).forEach((key) => {
if (data[key] instanceof Package.mongo.Mongo.Cursor) {
console.warn(
'Warning: you are returning a Mongo cursor from getMeteorData. '
+ 'This value will not be reactive. You probably want to call '