Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a method to reset a react component using ES6 classes to its initial state?

Tags:

reactjs

I am writing a game and when the game is over, I want it to reset to the initial state. I haven't found any meaningful information in the docs for this, so I've been playing around with adding a reset method to my Game class. First, I attempted doing the follow in hopes of creating a base class I could extend later, but using a variable for the component name fails:

class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      ...
    };
  }

  reset() {
    var node = ReactDOM.findDOMNode(this),
        ComponentName = this.constructor.name;
    if (node) {
      ReactDOM.unmountComponentAtNode(node);
      ReactDOM.render(<ComponentName />, node);
    }
  }

  ...
}

I moved on, and tried to hardcode the component name as follows:

class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      ...
    };
  }

  reset() {
    var node = ReactDOM.findDOMNode(this);
    if (node) {
      ReactDOM.unmountComponentAtNode(node);
      ReactDOM.render(<Game />, node);
    }
  }

  ...
}

This works really well, but I am wondering if there is a built-in way that is better, or a more generic way.

like image 288
Omnilord Avatar asked Mar 24 '16 09:03

Omnilord


2 Answers

Update Please disregard the previous answer, replaceState is obviously not available in the ES2015 class pattern. Anyway, another solution is to keep an instance of the game in a wrapper component's state.

Working fiddle: https://jsfiddle.net/dannyjolie/upktozt1/1/

This will just remove the old game from App's state when you reset to a new game, and a new game will take its place.

class App extends React.Component {
  constructor(props) {
    super(props);
    this.newGame = this.newGame.bind(this);
    this.state = {
      game: ()=><Game />
    };
  }

  newGame () {
    this.setState({
      game: () => <Game />
    });
  }

  render () {
    const ActiveGame = this.state.game;
    return (
      <div>
        <ActiveGame />
        <button onClick={this.newGame}>RESET GAME</button>
      </div>
    );
  }
}

class Game extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      foo: 'Bar'
    };
    this.onButtonClick = this.onButtonClick.bind(this);
  }

  onButtonClick () {
    this.setState({
      somethingElse: 'Hello',
      foo: 'Changed foo'
    });
  }

  render () {
    return (
      <div>
        <button onClick={this.onButtonClick}>Set state.somethingElse</button>
        <p>state.foo: {this.state.foo}</p>
        <p>state.somethingElse: {this.state.somethingElse || '(not defined yet)'}</p>
      </div>
    );
  }
}
like image 70
dannyjolie Avatar answered Nov 15 '22 08:11

dannyjolie


If you need only reset state then you can move default state into some function or variable and when you need reset state only call setState with value from this function or variable.

Example:

class Game extends React.Component {
    constructor(props) {
        super(props);
        this.state = this.getState(); // set state from getState result
        this.onButtonClick = this.onButtonClick.bind(this);
        this.onReset = this.onReset.bind(this);
    }

    getState() {
        return {
            number: 0
        }
    }

    onReset() {
        this.setState(this.getState()) // set state from getState result
    }

    onButtonClick () {
        this.setState({
            number: this.state.number + 1
        });
    }

    render () {
        return (
            <div>
                <button onClick={this.onButtonClick}>
                    Increment
                </button>
                <p>{this.state.number}</p>

                <button onClick={this.onReset}>
                    Reset
                </button>
          </div>
        );
    }
}

Example on JSFiddle

like image 38
Aleksandr Petrov Avatar answered Nov 15 '22 10:11

Aleksandr Petrov