Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle Meteor Data that requires state from child component?

Switching some code over in Meteor 1.3 to ES6+ React syntax. Component requires getting Meteor data, so I'm using a createComponent to replace getMeteorData(). The problem is, the old getMeteorData used state from the component, which isn't being accessed by the createContainer component.

Old code:

Component = React.createClass({
   mixins: [ReactMeteorData],
   getMeteorData() {
    var mo = this.state.currentMonth;
    var start = newDate(moment(mo).startOf('month'));
    return {
     events:     collections.events.find({
        $or:       qwry,
        startDate: { $gte: start },
        endDate:   { $lte: end }
      }).fetch(),
    }
  },
  render() {
   ...
  }
});

New Code Thus Far

class Component = React.Component {
 constructor(props) {
  super(props);
 }
 render() {
  ...
 }
}

export default createContainer(({params}) => {
var mo = this.state.currentMonth;
        var start = newDate(moment(mo).startOf('month'));
        return {
         events:     collections.events.find({
            $or:       qwry,
            startDate: { $gte: start },
            endDate:   { $lte: end }
          }).fetch(),
        }
}, Component);

Getting the error "cannot get currentMonth of undefined," since it's trying to access state. Any suggestions?

like image 465
ebrillhart Avatar asked Apr 05 '16 19:04

ebrillhart


1 Answers

You can split the old component into two partial components: one that holds the state and handles events, and a pure one that merely displays results. Make sure to pass event handlers as callbacks to the child component. Also note how the parent component uses the return value of the createContainer() function.

// Parent component, setState should go here
export default class StateHolder extends React.Component {
  constructor(params) {
    super(params);
    this.state = {myKey: 1};
  }

  incrementKey() {
    this.setState({myKey: this.state.myKey + 1});
  }

  render() {
    return <Container myKey={this.state.myKey} onClick={this.incrementKey.bind(this)} />;
  }
}

// Child component, renders only
class PureComponent extends React.Component {
  render() {
    return <div>
      {this.props.myValue}
      <button onClick={this.props.onClick}>click me</button>
    </div>;
  }
}

// Decorated child container. 
// Make sure to use this one in parent component's render() function!
let Container = createContainer((props) => {
  let doc = MyCollection.findOne({someKey: props.myKey});
  return {
    myValue: doc ? doc.someValue : null
  }
}, PureComponent);
like image 63
aedm Avatar answered Oct 21 '22 22:10

aedm