简体   繁体   中英

Loop through Meteor React components

In Meteor 1.4 with React I want to do a nested loop of rendering components, 2 rows of 6 items each.

Row 1
[unique_item] [unique_item] [unique_item] ...
Row 2
[unique_item] [unique_item] [unique_item] ...

How do I pass state to the createContainer function so that I can increment the counter to paginate the results?

Here's the code:

import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { createContainer } from 'meteor/react-meteor-data';

import { Items } from '../api/items.js';
import Item from './Item.jsx';
import '../../client/stylesheets/main.scss';

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      skipCount : 0
    };
  }

  renderItemRows(i) {
    return  ( 
      <div className="container-fluid">
          <div className="row">
             { this.renderItems(i) }
          </div>
        </div>   
      );
  }


  renderItems(i) {
   // i here has the right value...how do I pass into createContainer?
   return this.props.items.map((item) => (
      <Item key={item._id} item={item} />
    ));
  }

  render() {
    let rows = []; 
    for (let i=0;i<2;i++) {
      rows.push(this.renderItemRows(i));
    }
    return (<div>{rows}</div>);
  }
}


App.propTypes = {
  items: PropTypes.array.isRequired,
  skipCount: PropTypes.number,
};

export default createContainer(() => {
  // Hardcoded to 50 just to make sure the data pagination works
  const skipCount  = 50;
  Meteor.subscribe('items', skipCount);
  return {
    items: Items.find({}, { sort: { item : 1 }, limit : 6 }).fetch(),
  };
}, App);

After reading through this thread on the Meteor forums, createContainer() is passed as a stateless function so there's no way to pass information like this to it.

According to that thread, my only two options are:

  1. Creating a wrapper component ( ItemRow1.jsx and ItemRow2.jsx )
  2. Passing a parameter to the publish function via Session.get()

I tried No. 2, but it started reading Session.get hundreds of times a second and bringing my application to a halt.

No. 1 will work but seems incredibly repetitive just to paginate through a second row of data...is there no better way to do this?

If I correctly understand what you're trying to do, the easiest way to achieve that would be to create separate arrays of items for rows 1 and 2 in createContainer :

return {
  items1: Items.find({}, { sort: { item : 1 }, limit : 6 }).fetch(),
  items2: Items.find({}, { sort: { item : 1 }, skip: 6, limit : 6 }).fetch(),
};

You of course need to alter the propTypes as well:

items1: PropTypes.array.isRequired,
items2: PropTypes.array.isRequired,

Now in the renderItems method you can do this:

return this.props[`items${i+1}`].map((item) => (
  <Item key={item._id} item={item} />
));

Alternatively, since you just have two rows (and apparently no need to support any other number of rows), you could just get 12 items from the database, and then render the them in renderItems with slice like this:

const items = (i === 0) ? this.props.items.slice(0, 7) : this.props.items.slice(7);
return items.map((item) => (
  <Item key={item._id} item={item} />
));

It depends on your actual code which way is cleaner, so go with whatever you prefer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM