React native shows NaN when it is empty when calling the function from a conditional statement inside onPress

Viewed 69

The function isEmpty does not work, shows NaN when it is empty when calling the function from a conditional statement inside onPress. The function handleResulte is working but not the isEmpty.

I am new here in React Native and using youtube and Udemy to learn from tutorials.

when it is empty

state = {
    num1: '',num2: ''
}
inp1 = 0; inp2 = 0; 

handleNum1 = (text) => {
    this.inp1 = parseInt(text);
}
handleNum2 = (text) => {
    this.inp2 = parseInt(text);
}
handleResulte = () => {
    this.setState({
        num1: (this.inp1/(100+6)*(this.inp2/100)*(100-20)).toFixed(0)
    })
    this.setState({
        num2: (this.inp1/(100+6)*(this.inp2/100)*100).toFixed(0)
    })
}
isEmpty = () => { 
    this.setState({
        num1: 'is Empty'
}) 
this.setState({
    num2: 'is Empty'
})}
render() {
    return (
        <View style={styles.flexBox}>
            <View style={styles.inpBox}>
                <TextInput
                    style={styles.inps}
                    placeholder="Num1"
                    keyboardType="numeric"
                    onChangeText={this.handleNum1}
                />
                <TextInput
                    style={styles.inps}
                    placeholder="Num2"
                    keyboardType="numeric"
                    onChangeText={this.handleNum2}
                />       
            </View>
            <View style={styles.butBox}>
                    <TouchableOpacity
                        style = {styles.btn}
                        onPress={() => {
                            if (!this.state.num1){ this.isEmpty()} 
                            else {this.handleResulte()}
                        }}>
                        <Text style = {styles.btnText}>Press me</Text>
                    </TouchableOpacity> 
            </View>
            <View style={styles.resulteBox}>
                <Text style = {styles.boxText}>
                    {this.state.num1}
                </Text>
                <Text style = {styles.boxText}>
                    {this.state.num2}
                </Text>               
            </View>
        </View>
    );
}
}

2 Answers

Running parseInt on an empty string will give you NaN (not a number).

It's also not good practice to save your inp1 and inp2 as instance variables on your class. Holding them in state will signal React to re-render when they change.

I would keep inp1 and inp2 in state as strings (since they come from text inputs), and then expand your handleResulte method to handle the empty case. You wouldn't need your isEmpty method. (You can also set more than one state key in each setState call.)

You should begin by setting your state in the constructor of your class.

constructor() {
  this.state = {
    input1: '',
    input2: '',
    result1: 'is Empty',
    result2: 'is Empty'
  }
}

Then you can expand handleResulte to handle the empty cases.

handleResulte() {
  const parsedInput1 = parseInt(this.state.input1);
  const parsedInput2 = parseInt(this.state.input2);
  // set results to empty if inputs are NaN or zero
  if (!parsedInput1 || !parsedInput2) {
    this.setState({ result1: 'is Empty', result2: 'is Empty' });
    return;
  }

  this.setState({
    result1: // your math
    result2: // your math
  })
}

You could tell your inputs to store their text directly in inp1 and inp2.

        <TextInput
          ...
          onChangeText={text => this.setState({ inp1: text })}
        />
        <TextInput
          ...
          onChangeText={text => this.setState({ inp2: text })}
        />

Then, in your button, you can simply call handleResulte:

  ...
        <TouchableOpacity
          style={styles.btn}
          onPress={this.handleResulte}
        >
          ...

Full revised code below. Let me know if this makes sense.

constructor() {
  this.state = {
    inp1: '',
    inp2: '',
    num1: 'is Empty',
    num2: 'is Empty'
  }
}

handleResulte() {
  const parsedInp1 = parseInt(this.state.inp1);
  const parsedInp2 = parseInt(this.state.inp2);
  // set results to empty if inputs are not a number or zero
  if (!parsedInp1 || !parsedInp2) {
    this.setState({ num1: 'is Empty', num2: 'is Empty' });
    return;
  }

  this.setState({
    num1: (parsedInp1 / (100 + 6) * (parsedInp2 / 100) * (100 - 20)).toFixed(0),
    num2: (parsedInp1 / (100 + 6) * (parsedInp2 / 100) * 100).toFixed(0)
  })
}

render() {
  return (
    <View style={styles.flexBox}>
      <View style={styles.inpBox}>
        <TextInput
          style={styles.inps}
          placeholder="Num1"
          keyboardType="numeric"
          onChangeText={text => this.setState({ inp1: text })}
        />
        <TextInput
          style={styles.inps}
          placeholder="Num2"
          keyboardType="numeric"
          onChangeText={text => this.setState({ inp2: text })}
        />
      </View>
      <View style={styles.butBox}>
        <TouchableOpacity
          style={styles.btn}
          onPress={this.handleResulte}
        >
          <Text style={styles.btnText}>Press me</Text>
        </TouchableOpacity>
      </View>
      <View style={styles.resulteBox}>
        <Text style={styles.boxText}>
          {this.state.num1}
        </Text>
        <Text style={styles.boxText}>
          {this.state.num2}
        </Text>
      </View>
    </View>
  );
}

I find the answer and the whole code will be

import React from 'react';
import { StyleSheet, Text, View, TextInput, TouchableOpacity } from 'react-native';


export default class Counter1 extends React.Component {
    
    state = {
    input1: '',
    input2: '',
    input3: '',
    input4: '',
    resulte1: '',
    resulte2: '',
    resulte3: '',
    resulte4: ''
      }
    
handleResulte() {
    const parsedInput1 = parseInt(this.state.input1);
    const parsedInput2 = parseInt(this.state.input2);
    const parsedInput3 = parseInt(this.state.input3);
    const parsedInput4 = parseInt(this.state.input4);
    // set results to empty if inputs are not a number or zero
    if (!parsedInput1 || !parsedInput2 || !parsedInput3 || !parsedInput4) {
      this.setState({ resulte1: 'Fill in all the boxes' });
      return;
    }
  
    this.setState({
      resulte1: (parsedInput1 / (100 + parsedInput4) * (parsedInput2 / 100) * (100 - parsedInput3)).toFixed(0),
      resulte2: (parsedInput1 / (100 + parsedInput4) * (parsedInput2 / 100) * 100).toFixed(0),
      resulte3: (parsedInput1 / (100 + parsedInput4) * (parsedInput2 / 100) * parsedInput3).toFixed(0),
      resulte4: (parsedInput1 / (100 + 6) * (100 / 100) * parsedInput4).toFixed(0),
    })
  }
 

render() {
    return (
        <View style={styles.flexBox}>
            <View style={styles.inputBox}>
                <TextInput
                    style={styles.inputs}
                    placeholder="Num1"
                    keyboardType="numeric"
                    onChangeText={text => this.setState({ input1: text })}
                />
                <TextInput
                    style={styles.inputs}
                    placeholder="Num2"
                    keyboardType="numeric"
                    onChangeText={text => this.setState({ input2: text })}
                />
                <TextInput
                    style={styles.inputs}
                    placeholder="Num3"
                    keyboardType="numeric"
                    onChangeText={text => this.setState({ input3: text })}
                />
                <TextInput
                    style={styles.inputs}
                    placeholder="Num4"
                    keyboardType="numeric"
                    onChangeText={text => this.setState({ input4: text })}
                />
            </View>
            <View style={styles.butBox}>
                    <TouchableOpacity
                        style = {styles.btn}
                        onPress={()=>this.handleResulte()}>
                        <Text style = {styles.btnText}>Calculate</Text>
                    </TouchableOpacity> 
            </View>
            <View style={styles.resulteBox}>
                <Text style = {styles.boxText}>
                    {this.state.resulte1}
                </Text>
                <Text style = {styles.boxText}>
                    {this.state.resulte2}
                </Text>
                <Text style = {styles.boxText}>
                    {this.state.resulte3}
                </Text>
                <Text style = {styles.boxText}>
                    {this.state.resulte4}
                </Text>
            </View>
        </View>
    );
}
}

const styles = StyleSheet.create({
flexBox: {
    alignItems: 'center',
    paddingHorizontal: 10,
    backgroundColor:'ededed',
    flexDirection: 'column',
    flex: 1,
},


inputBox: {
    marginTop: 40,
    flexDirection: "row",
    justifyContent: 'space-between',
    alignItems: 'center',
    flex: 1,
},

inputs: {
    width: "20%",
    height: 50,
    textAlign: "center",
    backgroundColor:'white',
    marginRight: 10,
    borderRadius: 20,
},


butBox: {
    width: "80%",
    alignItems: 'center',
    justifyContent: 'center',
    paddingHorizontal: 10,
    flex: 1,
},
btn: {
    width: 300,
    alignItems: "center",
    backgroundColor: "#2196F3",
    padding: 10,
    marginVertical: 10,
    borderRadius: 20,
},
btnText: {
    fontSize: 16,
    color: 'white',
},

resulteBox: {
    width: '80%',
    alignItems: 'center',
    flex: 4,
},
boxText: {
    fontSize: 32,
    padding: 20,
}
});

Related