I've made this app with React:

Live-Demo here: http://n-or.de/simple-calculator/
It works well on desktop but on mobile the actual app isn't visible.
One just sees the background with the gradient. I've tested that with an iPhone 6s plus. Afterward I asked a friend to try it on her Android and she had the same blank background.
That's already the second React app with which I have this issue.
The mentioned other React app can be seen here: http://n-or.de/weather-app/
So I don't think it's attached to using some specific language feature.
Here's the JSX- and Sass-code of the calculator app:
// Main.jsx as starting point of the app.
var React = require('react');
var ReactDOM = require('react-dom');
var Calculator = require('./components/Calculator.jsx');
var NAV_BUTTONS = [
{ value: '+ Add',
operation: 'add'
},
{ value: '- Subtract',
operation: 'subtract'
},
{ value: 'x Multiply',
operation: 'multiply'
},
{ value: '/ Divide',
operation: 'divide'
}
];
ReactDOM.render(<Calculator navButtons={ NAV_BUTTONS } />, document.getElementById('app'));
// Calculator.jsx - Main app-component
var React = require('react');
var TextBox = require('./TextBox.jsx');
var Button = require('./Button.jsx');
var Calculator = React.createClass({
INIT_STATE: { a: 0,
b: 0,
placeholderText: 'Enter a number ...',
resultBox: '',
aClass: 'input-box',
bClass: 'input-box',
aDisabled: false,
bDisabled: false,
buttonsDisabled: 'disabled' },
operations: {
'add': function() {
return this.state.a + this.state.b;
},
'subtract': function() {
return this.state.a - this.state.b;
},
'multiply': function() {
return this.state.a * this.state.b;
},
'divide': function() {
return this.state.a / this.state.b;
}
},
getInitialState: function() {
return this.INIT_STATE;
},
updateNumbers: function(variable, reference) {
var val = parseFloat(reference.value);
var varClass = [variable + 'Class'];
if (typeof val === 'number' && !isNaN(val)) {
if (this.state[variable + 'Class'].indexOf('invalid-input') > -1) {
this.setState({
[varClass]: 'input-box'
})
}
this.setState({
[variable]: val,
buttonsDisabled: ''
});
} else {
this.setState({
[varClass]: [varClass] + ' invalid-input',
buttonsDisabled: 'disabled'
});
}
},
triggerOperation: function(operation) {
var result = this.operations[operation].call(this);
this.setState({
aDisabled: 'disabled',
bDisabled: 'disabled',
buttonsDisabled: 'disabled'
});
this.refs.resultBox.refs.inputElement.value = result;
},
resetForm: function() {
function resetElement(itemName, placeholder, disabled) {
this.refs[itemName].refs.inputElement.value = ''; // Value must be empty f. placeholder to appear.
this.refs[itemName].refs.inputElement.disabled = disabled;
this.refs[itemName].refs.inputElement.placeholder = placeholder;
}
resetElement.call(this, 'a', this.INIT_STATE.placeholderText);
resetElement.call(this, 'b', this.INIT_STATE.placeholderText);
resetElement.call(this, 'resultBox', this.INIT_STATE.resultBox, 'disabled');
this.setState({
a: 0,
b: 0,
aClass: 'input-box',
bClass: 'input-box',
buttonsDisabled: 'disabled'
});
},
render: function() {
var that = this;
var navButtons = this.props.navButtons.map(function(button) {
return (
<div>
<Button value={ button.value } classDiv="large-3 medium-6 column"
classButton="calculation-method nav-button"
handler={ that.triggerOperation } operation={ button.operation } disabled={ that.state.buttonsDisabled }/>
</div>
);
});
return (
<div className="calculator">
<div className="row">
<h1>Simple calculator</h1>
</div>
<div className="row">
<TextBox divClass="large-6 columns"
placeholder={ this.state.placeholderText }
id="a" textBoxClass={ this.state.aClass }
ref="a"
value={ this.state.a }
changeHandler={ this.updateNumbers }
variable="a"
disabled={ this.state.aDisabled }
/>
<TextBox divClass="large-6 columns"
placeholder={ this.state.placeholderText }
id="b" textBoxClass={ this.state.bClass }
ref="b"
value={ this.state.b }
changeHandler={ this.updateNumbers }
variable="b"
disabled={ this.state.bDisabled }
/>
</div>
<div className="row">
{ navButtons }
</div>
<div className="row">
<TextBox divClass="medium-9 columns"
placeholder={ this.INIT_STATE.resultBox }
ref="resultBox" textBoxClass="input-box"
disabled="disabled" />
<Button value="Clear" classDiv="medium-3 columns"
classButton="attention nav-button"
handler={ this.resetForm } />
</div>
</div>
);
}
});
module.exports = Calculator;
// Button component
var React = require('react');
var Button = React.createClass({
render: function() {
function notify(e) {
this.props.handler(e.target.dataset.operation);
}
return (
<div className={ this.props.classDiv }>
<button href='#' className={ this.props.classButton }
onClick={ notify.bind(this) }
data-operation={ this.props.operation }
disabled={ this.props.disabled } >
{ this.props.value }
</button>
</div>
);
}
});
module.exports = Button;
// TextBox component
var React = require('react');
var TextBox = React.createClass({
notify: function() {
let item = this.refs.inputElement;
this.props.changeHandler(item.dataset.variable, item);
},
render: function() {
return (
<div className={ this.props.divClass }
ref={ this.props.id }>
<input type="text"
placeholder={ this.props.placeholder}
ref="inputElement"
className={ this.props.textBoxClass }
disabled={ this.props.disabled }
onChange={ this.notify }
data-variable={ this.props.variable }
/>
</div>
);
}
});
module.exports = TextBox;
$lightChange: 25%;
$borderRadius: 6px;
@mixin addPseudoClasses($selector, $color) {
#{$selector}:visited, #{$selector}:hover {
color: white;
}
#{$selector}:hover {
background: linear-gradient(lighten($color, $lightChange), $color);
color: white;
cursor: pointer;
}
#{$selector}:active {
opacity: 0.6;
box-shadow: 1px 1px 0 black;
}
}
html, body {
height: 100%;
}
body {
background: linear-gradient(to top, #403B4A , #E7E9BB);
}
.nav-button {
text-decoration: none;
color: green;
padding: 10px 20px;
text-align: center;
font-weight: 900;
font-size: 1.2rem;
margin-bottom: 16px;
display: inline-block;
width: 100%;
border-radius: $borderRadius;
letter-spacing: 1px;
box-shadow: 2px 2px 0 black;
}
.nav-button[disabled] {
color: crimson;
}
.calculation-method {
background: linear-gradient(to top, #abbaab ,#ffffff);
}
@include addPseudoClasses('.calculation-method', #344334);
h1 {
text-align: center;
margin: 20px 0 30px;
letter-spacing: 2px;
}
.attention {
background: linear-gradient(to top, darken(#ED4264, $lightChange), #FFEDBC);
text-transform: uppercase;
color: white;
}
@include addPseudoClasses('.attention', red);
.invalid-input {
border-color: red !important;
background-color: pink !important;
}
input[type=text] {
border-radius: $borderRadius !important;
box-shadow: inset 1px 1px 0 black;
padding-left: 20px;
font-weight: 900;
}
The full project-code is on GitHub: https://github.com/mizech/simple-calculator
And in case someone likes to see the code of the second app: https://github.com/mizech/weather-app
If someone has an idea what causes the issue with the blank page then I would really much appreciate it as an answer.
Just open the app with a browser console and you will see an error message (or open it on Safari on the desktop):
SyntaxError: Unexpected identifier 'item'
That is caused by let item = this.refs.inputElement;. Not all browsers support ES6 just yet. You have to transpile ES6 to ES5 using Babel or Google Traceur.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With