keeping track of history in a React component using Immutable.js

536 Views Asked by At

What are some patterns one can employ when using Immutable.js in React in order to implement a history / "go back in time" feature? To understand the issues I built a simple React application that displays a random number and provides three buttons:

  • generate new random number
  • go back in time
  • go forward in time.

This is the GUI:

enter image description here

And here's my code:

const React = require('react');

import {List} from 'immutable';
import {assert} from 'chai';

const App = React.createClass({
    getInitialState: function() {
        return {
            history: List([Math.random()]),
            currentTime: 0,
            maxTimeReached: 0
        };
    }
    , newRandomNumber() {
        const newHistory = this.state.history.push(Math.random());
        this.setState({history: newHistory
                       , currentTime: this.state.currentTime+1
                       , maxTimeReached: this.state.maxTimeReached+1
                      });
    }
    , backInTime() {
        this.setState({currentTime: this.state.currentTime-1});
    }
    , forwardInTime() {
        this.setState({currentTime: this.state.currentTime+1});
    }
    , componentWillUpdate(_, nextState) {
        // sanity checks
        assert.isTrue(nextState.currentTime>=0);
        assert.isTrue(nextState.currentTime<=nextState.maxTimeReached);
    }
    , render: function() {
        return (
            <div>
                <div>{this.state.history.get(this.state.currentTime)}</div>
                <div>
                    <button onClick={this.newRandomNumber}
                        disabled={this.state.currentTime<this.state.maxTimeReached}>new random
                    </button>
                </div>
                <div>
                    <button onClick={this.backInTime}
                        disabled={this.state.currentTime==0}>&lt;
                    </button>
                    <button onClick={this.forwardInTime}
                        disabled={this.state.currentTime===this.state.maxTimeReached}> &gt;
                    </button>
               </div>
            </div>
        );
    }
});

export default App;

My questions are:

  1. what exactly is Immutable.js buying us in this simplistic example in terms of being able to go back in time? I think the answer is nothing. The state of the application is effectively the counter and being a primitive type it is immutable out of the box. But perhaps in an application with a more complex state and provided that the state does not change much from one step to the next, then immutable's structural sharing would allow us to save the entire history of our app using less memory. Is my understanding correct?
  2. we'll need a structure to hold the history of our application. This could be either a mutable native array or an immutable list. In the example above I used an immutable list but are there any benefits over using a mutable native array? I don't see any.
  3. further to #2 should we keep the history of our component in this.props.state or as a member property of the class?
  4. The only benefit I see that immutable brings to the table when it comes to being able to go back in time is saving space due to structural sharing so it is only worth it when the component has voluminous state and it doesn't change that much from one step to the next (e.g. a game grid). Am I missing anything?
0

There are 0 best solutions below