Porting HAMURABI.BAS to JavaScript: Starting a React Interface

It’s been a few weeks since the last post in this series. I’ve spent some time making an interface in React. It’s simple, but also a decent demo.  Here’s the demo.

The page doesn’t do anything, but it shows off a few nice features that React does well.  I’m a noob with React, so I’m not going to write a tutorial. There are a few good ones out there if you just search.

If you look at the demo, you’ll see a simple screen, with output at the left, and an input panel at the right.

The code for the panel is pretty long:

class Plan extends Component {
    constructor(props) {
        super(props);
        this.state = { 
            buysell: 15,
            plant: 15,
            feed: 15
        };
    }

    changeBuySell(evt) {
        this.setState({buysell: evt.target.value}); 
    }

    changePlant(evt) {
        this.setState({plant: evt.target.value}); 
    }

    changeFeed(evt) {
        this.setState({feed: evt.target.value}); 
    }

    render() {
        return (
            <div className="plan">
                <div>
                    Plan for Next Year
                </div>
                <form>
                    <Range label="Buy/Sell Land" min="10" max="20" 
                        value={this.state.buysell} onChange={this.changeBuySell.bind(this)} />
                    <Range label="Plant Grain" min="10" max="40" 
                        value={this.state.plant} onChange={this.changePlant.bind(this)} />
                    <Range label="Feed People" min="10" max="40" 
                        value={this.state.feed} onChange={this.changeFeed.bind(this)} />
                    <PlayButton />
                </form>
            </div>
        );
    }
}

The React tutorial uses anonymous functions, but I ended up going with names functions. The calling convention, this.func.bind(this), is ugly, but having the code separate is preferable.

The control maintains some state. There will probably be some validation functions in the game engine that will allow us to validate individual values against the entire proposed next move. We can encourage, or force, valid input by showing some error messages.

We also have a component for the Range inputs. This component decorates the standard HTML range input.

class Range extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        const {label, min, max, value, onChange} = this.props;
        return (
            <div className="range">
                <div className="range__title">
                    {label}
                </div>
                <div className="range__numbers">
                    <span className="range__numbers_left">
                        {min} 
                    </span>
                    <span className="range__numbers_center">
                        {value}
                    </span>
                    <span className="range__numbers_right">
                        {max}
                    </span>
                </div>
                <input className="range__slider" value={value} min={min} max={max} type="range" onChange={onChange} />
            </div>
        );
    }
}

That’s a lot of HTML that’s put into the component, but it renders perfectly.

I also used Block Element Modifier (BEM) naming for the CSS classes. It looks excessive, but it makes it really easy to style the element. It eliminates most of the element hierarchy.

Code’s attached, but most of it is in flux. I’m still need to figure out how the game is going to integrate wit this user interface.

App

Leave a Reply