langlant
langlant

Reputation: 97

React.js display output on button press

I have an app that calculates the distance traveled and bearing between one coordinate to another. What I want to happen onPress is to display the distance and bearing beneath the button. I've been trying for some time and cannot figure out how to supply an output. I have the calculate class that exports to the app.js which controls the display.

After pressing calculate the only output is: Bearing: NaN.

What it should be printing beneath the input boxes and buttons is:

Distance: (distance)km
Bearing: (bearing)

Any guidance would be very much appreciated.

Calculate.js

import React, { useState} from 'react';
import {StyleSheet, Text, View, TextInput} from 'react-native';
import {Button} from 'react-native-elements';
import {computeDistance, computeBearing} from './Calculations';

const Calculate = ({buttonTitle, lat1, lon1, lat2,lon2, distance, bearing}) => {
    const [state, setState] = useState({lat1: '', lon1: '', lat2: '', lon2: '', distance: '', bearing: ''});

    const updateStateObject = (vals) =>{
        setState({
            ...state,
            ...vals,
        });
    };
    return (
        <View style={styles.container}>
            <TextInput 
                placeholder = 'Starting latitude' 
                onChangeText = {(lat1) => updateStateObject({lat1: lat1})} //or you could do (val) => {setName(val);}
                value = {state.lat1}/>
            <TextInput 
                placeholder = 'Starting longitude' 
                onChangeText = {(lon1) => updateStateObject({lon1: lon1})} //or you could do (val) => {setName(val);}
                value = {state.lon1}/>
            <TextInput 
                placeholder = 'Ending latitude' 
                onChangeText = {(lat2) => updateStateObject({lat2: lat2})} //or you could do (val) => {setName(val);}
                value = {state.lat2}/>
            <TextInput 
                placeholder = 'Ending longitude' 
                onChangeText = {(lon2) => updateStateObject({lon2: lon2})} //or you could do (val) => {setName(val);}
                value = {state.lon2}/>
            <Button 
            title= {buttonTitle}
            onPress = {() =>{
               state.distance = computeDistance({lat1: lat1}, {lon1: lon1}, {lat2: lat2}, {lon2: lon2});
               state.bearing = computeBearing({lat1: lat1}, {lon1: lon1}, {lat2: lat2}, {lon2: lon2})
                updateStateObject({distance: `Distance: ${state.distance}`});
                updateStateObject({bearing: `Bearing: ${state.bearing}`});
            }} />
            <Text> {state.distance}</Text>
            <Text> {state.bearing}</Text>
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: '#fff',
      alignItems: 'center',
      justifyContent: 'center',
    },
  });
export default Calculate;

Calculations.js

 // Converts from degrees to radians.
 function toRadians(degrees) {
    return (degrees * Math.PI) / 180;
  }

  // Converts from radians to degrees.
  function toDegrees(radians) {
    return (radians * 180) / Math.PI;
  }

  // Computes distance between two geo coordinates in kilometers.
  export function computeDistance(lat1, lon1, lat2, lon2) {
    console.log(`p1={${lat1},${lon1}} p2={${lat2},${lon2}}`);
    var R = 6371; // km (change this constant to get miles)
    var dLat = ((lat2 - lat1) * Math.PI) / 180;
    var dLon = ((lon2 - lon1) * Math.PI) / 180;
    var a =
      Math.sin(dLat / 2) * Math.sin(dLat / 2) +
      Math.cos((lat1 * Math.PI) / 180) *
        Math.cos((lat2 * Math.PI) / 180) *
        Math.sin(dLon / 2) *
        Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c;
    return `${round(d, 3)} km`;
  }

  // Computes bearing between two geo coordinates in degrees.
 export function computeBearing(startLat, startLng, destLat, destLng) {
    startLat = toRadians(startLat);
    startLng = toRadians(startLng);
    destLat = toRadians(destLat);
    destLng = toRadians(destLng);

    var y = Math.sin(destLng - startLng) * Math.cos(destLat);
    var x =
      Math.cos(startLat) * Math.sin(destLat) -
      Math.sin(startLat) * Math.cos(destLat) * Math.cos(destLng - startLng);
    var brng = Math.atan2(y, x);
    brng = toDegrees(brng);
    return (brng + 360) % 360;
  }

  function round(value, decimals) {
    return Number(Math.round(value + "e" + decimals) + "e-" + decimals);
  }

Edit: updated Calculate.js and added Calculations.js

same problem still persists though.

Upvotes: 1

Views: 296

Answers (1)

Bhuwan Chandra
Bhuwan Chandra

Reputation: 315

I think in your Calculate component, you are passing objects into your functions but in Calculations.js your functions are expecting variables which are simple values not objects. And the other thing is that the value you are passing in form of objects is the one you are getting as props, not the one you have setted in state, you should use state.lat1, etc.

on your function call, you should change the arguments you are passing into that function

state.distance = computeDistance(state.lat1, state.lon1,state.lat2, state.lon2);

and same in other function call

state.bearing = computeBearing(state.lat1, state.lon1, state.lat2, state.lon2);

and also in your round function in Calculation.js, you are contaminating number with string which will again result in NaN(since the end value will be a string).

Number(Math.round(value + "e" + decimals) + "e-" + decimals);

Upvotes: 1

Related Questions