Home > Software engineering >  Running into "TypeError: Cannot read properties of undefined (reading 'num1') (14)&qu
Running into "TypeError: Cannot read properties of undefined (reading 'num1') (14)&qu

Time:05-01

I can't tell what's wrong with my code, but I'm running into this TypeError. Here's my code; I'm trying to create a simple calculator with buttons and the code is unfinished.

import React, { Component } from 'react';
import { AppRegistry, Text, View, StyleSheet, TextInput, TouchableHighlight, Dimensions } from 'react-native';
import Constants from 'expo-constants';

let deviceHeight = Dimensions.get('window').height;
let deviceWidth = Dimensions.get('window').width;

export default class App extends Component {
    
    state = {
        num1: 0,
        num2: 0,
        operation: ' ',
        answer: Number(this.state.num1)   Number(this.state.num2)
    };

The error occurs on line 14: answer: Number(this.state.num1) Number(this.state.num2)

    plus = () => {
        this.setState({
            operation: ' '
        }),
        this.setState({
            answer: Number(this.state.num1)   Number(this.state.num2)
        })
    };
    
    minus = () => {
        this.setState({
            operation: '-'
        }),
        this.setState({
            answer: Number(this.state.num1) - Number(this.state.num2)
        })
    };
    
    multiply = () => {
        this.setState({
            operation: 'x'
        }),
        this.setState({
            answer: Number(this.state.num1) * Number(this.state.num2)
        })
    };
    
    divide = () => {
        this.setState({
            operation: '/'
        }),
        this.setState({
            answer: Number(this.state.num1) / Number(this.state.num2)
        })
    };
    
    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.title}>
                    Calculator
                </Text>
                <View style={styles.textInputContainer}>
                    <TextInput style={styles.textInput}
                        keyboardType = 'numeric'
                        onChangeText={(num1) => this.setState({num1})}
                        value={this.state.num1}
                    />
                    
                    <Text style={styles.textInput}>
                        {this.state.operation}
                    </Text>
                    
                    <TextInput style={styles.textInput}
                        keyboardType = 'numeric'
                        onChangeText={(num2) => this.setState({num2})}
                        value={this.state.num2}
                    />
                </View>
                
                <View style={styles.textInputContainer}>
                    
                    <TouchableHighlight
                        style={styles.button}
                        onPress={this.plus}
                    >
                        <Text style={styles.title}>
                             
                        </Text>
                    </TouchableHighlight>
                </View>
            </View>
        );
    }
}

This is what I have so far, as well as a stylesheet. If there's any other errors you can spot, I'd appreciate all the help I can get. Thank you.

CodePudding user response:

You are trying to access the state on initial setup. This is not possible.

Hence,

state = {
        num1: 0,
        num2: 0,
        operation: ' ',
        answer: Number(this.state.num1)   Number(this.state.num2)
    };

does not work. Since this is the initial state, you can just set answer to zero.

state = {
        num1: 0,
        num2: 0,
        operation: ' ',
        answer: 0
    };

Changing answer afterwards is then possible.

There is another possible issue in your code. You set the state to a new object which does not contain the attributes of the object's definition. Furthermore, you set the state twice for setting answer and operation. This will trigger two rerenders, which is unnecessary. You can set everything at once as follows using the spread-syntax and override the values of the state that you want to override.

multiply = () => {
        this.setState(previousState => ({
            ...previousState,
            operation: 'x',
            answer: previousState.num1 * previousState.num2
        })),
    };
  • Related