cluster1
cluster1

Reputation: 5674

React : Application works on desktop but on mobile a blank page is shown

I've made this app with React:

calculator app

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.

Upvotes: 3

Views: 8348

Answers (3)

Isaac Borbon Miquirray
Isaac Borbon Miquirray

Reputation: 109

Your are probably seeing your app with Redux Devtools extension in your desktop. Delete it and see what errors does the console give you.

In my case my Store file was still with Devtools active.

    const store = createStore(
      rootReducer, 
      compose(applyMiddleware(thunk),
      window.__REDUX_DEVTOOLS_EXTENSION__ && 
      window.__REDUX_DEVTOOLS_EXTENSION__())
    );

To solve this I just deleted Redux Devtools extension code

    const store = createStore(
      rootReducer, 
      compose(applyMiddleware(thunk))
    );

Upvotes: 1

Piotr Berebecki
Piotr Berebecki

Reputation: 7468

The issue seems to be caused by the fact that the mobile browsers that you have tested are not able to read some of the css properties you have specified. Adding vendor prefixes should solve the problem.

For example, at the moment your pages render fine on an Android phone when using Chrome browser, but when using the Samsung stock internet browser only the gradient background can be seen.

Upvotes: 1

str
str

Reputation: 44969

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.

Upvotes: 4

Related Questions