Charlie
Charlie

Reputation: 15247

Call method on ES6 class instance of React.Component

I'm brand new to React and I'm using it in combination with ES6 classes. I have a class that inherits from React.Component and renders DOM based on a single property in its state. Here's how that looks:

class LoadingScreen extends React.Component {
  constructor(props) {
    super(props);
    this.state = { state: 'isHidden' };

  showTrying() {
    this.setState({ state: 'isTrying' });
  }

  hideAll() {
    this.setState({ state: 'isHidden' });
  }

  render() {
    switch (this.state.state) {

    case 'isHidden':
      return null;

    case 'isTrying':
      // Returns a bunch of DOM elements
  }
}

In a parent class, that is not a React component (I'm attempting to migrate existing code that uses no framework), I want to:

  1. Create an instance of LoadingScreen
  2. Call React.render to insert it in the DOM
  3. Call methods such as hide or showTrying on that instance to update its state

I've tried:

this.loadingScreen = new LoadingScreen();
React.render(this.loadingScreen, mountNode); // React invalid component error

// Later on...
this.loadingScreen.showTrying();

And also tried:

this.loadingScreen = React.render(React.createElement("LoadingScreen"), mountNode);

// Later on...
this.loadingScreen.showTrying(); // Undefined is not a function

Clearly I'm missing something fundamental here. :)

Upvotes: 1

Views: 2995

Answers (2)

WiredPrairie
WiredPrairie

Reputation: 59763

It would be more common that you'd set a property on the LoadingScreen component instance to control the visibility of the internal representation rather than adjusting the state via a function call on the object instance.

class LoadingScreen extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    switch (this.props.mode) {
        case 'isHidden':
          return null;
        case 'isTrying':
          // Returns a bunch of DOM elements
    }
  }
}

LoadingScreen.propTypes = { 
    mode: React.PropTypes.string
};
LoadingScreen.defaultProps = { 
    mode: 'isTrying'
};

Then, from the parent, you'd do something like this for example:

var currentMode = "isTrying";
React.render(<LoadingScreen mode={ currentMode } />, mountNode);

Or, another pattern is that the parent container/component uses the value of the property (I've called mode) to just not create and render the LoadingScreen component at all.

If the LoadingScreen needs to, you could copy the property value into local state as you've done.

Upvotes: 3

Alexandre Kirszenberg
Alexandre Kirszenberg

Reputation: 36408

Your second approach was close.

The first argument to React.createElement can either be a string (div, span, etc.) or a subclass of React.Component. In your case, the first argument should be LoadingScreen.

this.loadingScreen = React.render(React.createElement(LoadingScreen), mountNode);

this.loadingScreen.showTrying(); 

Upvotes: 1

Related Questions