I wrote a React app to adjust the serving size of a recipe. For example, if the recipe serves 4 people and requires 4 eggs, scaling it down to serve only 1 person should only require 1 egg. I try to also keep the units singular/plural accordingly while converting units when they become too big or too small. These features are written in plain JS, but I'd be curious to hear if it would be more appropriate to do this in React and how.
Relevant code snippets:
const RECIPES = [{
id: 'pasta-dough',
name: 'Pasta Dough',
serves: 4,
ingredients: [
{quantity: '4', unit: 'eggs'},
{quantity: '4', unit: 'cups', item: 'flour'},
// Note that the quantity below would normally be '1/4'.
{quantity: '.25', unit: 'cup', item: 'olive oil'},
{quantity: '1', unit: 'tablespoon', item: 'salt'}
]
}];
const Recipe = React.createClass({
getInitialState: function() {
return {
serves: this.props.serves,
scale: 1
};
},
onChange: function(e) {
const serves = Math.floor(Math.abs(e.target.value));
this.setState({
serves: serves,
scale: serves / this.props.serves
});
},
render: function() {
return (
<section>
<h1>{this.props.name}</h1>
<h2>
Serves
<input
type="number" min="0"
value={this.state.serves}
/* TODO: Smarter default step. */
step={this.props.serves / 4}
onChange={this.onChange} />
</h2>
<Ingredients ingredients={this.props.ingredients} scale={this.state.scale} />
</section>
);
}
});
const Ingredients = React.createClass({
render: function() {
return (
<ul>
{this.props.ingredients.map((ingredient, i) =>
<Ingredient key={i} scale={this.props.scale} {...ingredient} />
)}
</ul>
);
}
});
const Ingredient = React.createClass({
render: function() {
// Commenting out the code that depends on other code libraries.
// Want to keep this code review as simple as possible.
// const quantity = new Quantity(this.props.quantity).multiply(this.props.scale);
const unit = this.props.unit;
// const measurement = new Measurement(quantity, unit).convertUnits();
const quantity = this.props.quantity * this.props.scale;
const measurement = `${quantity} ${unit}`
return(
<li>{measurement.toString()} {this.props.item}</li>
);
}
});
RECIPES.forEach((recipe, i) => {
ReactDOM.render(
<Recipe key={recipe.id} index={i} {...recipe}/>,
document.getElementById(recipe.id));
});
document.querySelector('h2 input').focus();
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="pasta-dough"></div>
Demo: https://rviscomi.github.io/scale-recipe-react/
Source: https://github.com/rviscomi/scale-recipe-react
I'm new to React and would really appreciate advice on writing more semantic React. Some specific areas I'm interested in:
- use of state vs props
- mounting
- component organization
- static methods
Things I'm not interested to get feedback on:
- general JS style
- ES6, unless it directly affects React
- markup semantics