Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve `this` in converting React module to ES6 class

I have a React module that works fine in ES5. I am converting it to ES6 and using 6to5 for the conversion. Everything transpiles fine, but I get a runtime error when I am trying to set my props. When I drop a debugger and look at this, I see that this is the EventEmitter and not the class. Here is my code:

var React = require('react');

import CalendarStore from './../stores/calendar.store.js';

function getAppointments() {
  return {appts: CalendarStore.getAppts()}
}

export default class extends React.Component{
  constructor(props) {
    super(props);
    this.props = {
      view: 'weeks'
    }
  }

  changeView(child, view) {
    this.setProps({view: view});
  }

  componentWillMount() {
     CalendarStore.addChangeListener(this._onChange);
  }

  _onChange() {
    this.setProps(getAppointments());
  }

  ....
};

The place I am having the issue is in my changeView function. When it is transpiled down it looks like this:

  _onChange: {
      value: function _onChange() {
        this.setProps(getAppointments());
      },
      writable: true,
      configurable: true
    }

Again, inside that function, this is my EventEmitter. What is the way to fix this?

like image 281
jhamm Avatar asked Feb 05 '15 13:02

jhamm


Video Answer


1 Answers

this.setProps is deprecated, use state for this. It'll give you this warning in 0.13:

Warning: setProps(...) is deprecated in plain JavaScript React classes.

Also es6 class methods aren't autobound, so you need to bind it manually. You can either use .bind(this), or use arrow functions. For external emitters you do need to keep a reference, though.

You can just get rid of _onChange:

this._calendarListener = e => this.setState({things: e});
CalendarStore.addChangeListener(this._calendarListener);

Or bind in the constructor:

constructor(props){
   ...
   this._onClick = this._onClick.bind(this);
}

Don't forget to unbind the event in componentWillUnmount:

componentWillUnmount(){
    CalendarStore.removeChangeListener(this._onClick);
    // or 
    CalendarStore.removeChangeListener(this._calendarListener);
}

Adding event listeners should be done in componentDidMount, not componentWillMount. The constructor replaces componentWillMount in es6 classes.

This code is very bad... you're overriding the props react sets:

this.props = {
  view: 'weeks'
}

Just replace all occurrences of 'props' with 'state' in your code, and all will be good. Also you probably want the store's initial state.

this.state = {
  view: 'weeks',
  things: CalendarStore.getAppts()
}

Also, createClass isn't going away any time soon, so feel free to continue using it. It's often simpler. Stores should generally be handled by mixins, which is trivial with createClass, but more difficult to do right in es6 classes. I have a small library for mixins with react and es6 classes.

like image 63
Brigand Avatar answered Jan 04 '23 20:01

Brigand