React Komposer + Repeating Containers + Dirty Props + React


#1

Currently have three levels of classes

Homepage -> calls into the ListCountries container which composes the component version of itself.

ListCountries subscribes to a publish all countries. which grabs all the records in the country collection and builds out a map. For Each map, it calls into the NewsList Container which composes a component version of itself

NewsList subscribes to articles that have in their country array the objectId for the passed in country. Limit 5.

Whats weirdly happening is that its correctly pulling the records but if one Newslist is pulling it in then a majority of them also pull them in. I think I am dirting the props somewhere along the lines but I’m not sure how to fix this…

Any thoughts?


#2

Sounds like you don’t specify a selector in the query for each component (or don’t pass it in the props). Can you provide some code? Without it is hard to say it :wink:


#3

Here is the code:

  Meteor.publish('articles.countryList', function(country) {
    var c = Country.findOne({name: country});
    const cursor = Articles.find({country: c._id},{limit: 5});
    return cursor;
  });
  Meteor.publish('country.all', function () {
    const selector = {};
    const options = {
      // fields: {_id: 1, title: 1},
      // sort: {createdAt: -1},
      // limit: 10
    };

    return Country.find(selector, options);
  });

Country List

Container (Composer)

import {useDeps, composeWithTracker, composeAll } from 'mantra-core';
import ListCountries from '../../components/home/ListCountries';

export const composer = ({context, clearErrors, country}, onData) => {
  const {Meteor, Collections} = context();
  if (Meteor.subscribe('country.all').ready()) {
    const options = {};
    const records = Collections.Country.find().fetch();
    onData(null, {records});
  } else {
      onData();
  }
};

export default composeAll(composeWithTracker(composer),useDeps())(ListCountries);

Component

import React from 'react';
import CountryList from '../../containers/home/CountryList';

class ListCountries extends React.Component {
  constructor(props) {
    super();
    this.state = props;
  }
  render() {
    var count = 0;
    const countryModules = this.state.records.map(function(country) {
      count++;
      return <CountryList key={country.name+count} country={country.name} />
    });
    return (<div>
      <h2>View News By Country</h2>
      {countryModules}
    </div>);
  }
}

export default ListCountries;

NewsList (CountryList for Container)

Container

import {useDeps, composeWithTracker, composeAll } from 'mantra-core';
import NewsList from '../../components/home/NewsList';

export const composer = ({context, clearErrors, country}, onData) => {
  const {Meteor, Collections} = context();
  if (Meteor.subscribe('articles.countryList',country).ready()) {
    const options = {};
    const records = Collections.Articles.find().fetch();
    onData(null, {records});
  } else {
      onData();
  }
};

export default composeAll(composeWithTracker(composer),useDeps())(NewsList);

Component

import React from 'react';
import DOMPurify from 'dompurify';

class NewsList extends React.Component {
  constructor(props) {
    super();
    this.state = props;
  }
  render() {
    var count = 0;
    const articles =  this.state.records.map(function(article) {
      var clean = DOMPurify.sanitize(article.content, {ALLOWED_TAGS: []});
      count++;
      return <li key={this.state.country + article._id.valueOf() + count}><a href="#"><h4>{article.title}</h4><p>{clean.substring(0,97) + '...'}</p></a></li>
    },this);
      return (<div className='industryList'>
        <h3>{this.state.country || 'Loading'}</h3>
        <ul>
          {articles}
        </ul>
      </div>);
  }
}

export default NewsList;

#4

const records = Collections.Country.find().fetch();

You are reading out ALL records in this collection. In one component you subscribe to “country.all”, in the other component to “articles.countryList”. The records belong to the same collection “Country” so the sum of all found records will be returned if you query with .find()

You have to add a selector to .find in the container for each component (in your case the same as in the publish method).

So as example for your second container (NewsList):

const records = Collections.Country.find({country: country}).fetch()


#5

Ah that makes sense. Thank you!