Utilize the useState() hook to add an object and display its data in a React Native

Here is a function I am working with:

const [dataLoc, setDataLoc] = useState({date: "No data received yet from sensor", coords: {}});

This is where I set the location:

Geolocation.getCurrentPosition(
      location => {
        const date = dateToString(location.timestamp);
        const coords = location.coords
        setDataLoc({date, coords})
      }
)

The coords interface looks like this:

export interface GeoCoordinates {
    latitude: number;
    longitude: number;
    accuracy: number;
    altitude: number | null;
    heading: number | null;
    speed: number | null;
    altitudeAccuracy?: number | null;
}

Imported from:

import Geolocation from 'react-native-geolocation-service';

I am trying to render the data as follows:

<Text style={styles.data}>{dataLoc.coords.latitude}</Text>

However, I am encountering an error message that says:

error: SyntaxError: .../App.tsx: Unexpected token

I cannot access any properties of the object because it is empty {}, as declared in useState().

Is there a way for me to add coordinates to dataLoc without explicitly defining them and still be able to retrieve the object elements or define values as numbers or null?

I have also attempted to define it in useState() as:

const [dataLoc, setDataLoc] = useState({
  date: "No data received yet from sensor", 
  coords: { 
    latitude: 0,
    longitude: 0,
    altitude: 0,
    accuracy: 0,
    altitudeAccuracy: 0,
    heading: 0,
    speed: 0
  }
});

But then I receive the following error:

Type '{ latitude: number; longitude: number; altitude: number 
| null; accuracy: number; altitudeAccuracy: number | null; 
heading: number | null; speed: number | null; }' is not 
assignable to type '{ latitude: number; longitude: number; 
altitude: number; accuracy: number; altitudeAccuracy: number; 
heading: number; speed: number; }'.
Types of property 'altitude' are incompatible.
Type 'number | null' is not assignable to type 'number'.
Type 'null' is not assignable to type 'number'.

Answer №1

const [locationData, setLocationData] = useState<{
  date: string;
  coords: GeoCoordinates;
}>({
  date: '', 
  coords: {} as GeoCoordinates,
});
/*
 * Insert your additional code here
 */

// Call this function wherever needed (e.g., in useEffect)
const _updateLocation = () => {
  // Check location permission first
  Geolocation.getCurrentPosition(
    ({timestamp, coords}) => {
      const date = convertTimestampToString(timestamp);
      setLocationData({date, coords});
    },
    error => console.log(error),
  );
};
/*
 * Insert your additional code here
 */
return (
  <Text style={styles.data}>
    {locationData.coords?.latitude}
  </Text>
);

Answer №2

It is essential to specify the type of your state value explicitly since it cannot be inferred from the initial value.

For instance, if your state value is a number, there is no need for a type annotation.

const [value, setValue] = useState(0); // TypeScript infers the number type

setValue(53); // Ok
setValue('some string'); // Error

However, if your value can be either a number or a string, TypeScript cannot infer that and we must pass the type using a generic useState function.

const [num, setNum] = useState(0); // TypeScript infers the number type
const [value, setValue] = useState<string | number>(0); // We explicitly indicate string | number

setNum('some string'); // Error
setValue('some string'); // Ok

In regard to your specific example, considering how you initialize your state like this.

const [dataLoc, setDataLoc] = useState({
  date: "No data received yet from sensor", 
  coords: { 
    latitude: 0,
    longitude: 0,
    altitude: 0,
    accuracy: 0,
    altitudeAccuracy: 0,
    heading: 0,
    speed: 0
  }
});

The type TS infers from this initialization is as follows,

{
  date: string;
  coords: { 
    latitude: number;
    longitude: number;
    altitude: number;
    accuracy: number;
    altitudeAccuracy: number;
    heading: number;
    speed: number;
  };
}

However, this may not accurately represent the data, so defining the type or obtaining it from a library would help and passing it to useState.

interface DataLoc {
  date: string,
  coords: { 
    latitude: number;
    longitude: number;
    accuracy: number;
    altitude: number | null;
    heading: number | null;
    speed: number | null;
    altitudeAccuracy?: number | null;
  };
}

const [dataLoc, setDataLoc] = useState<DataLoc>({
  date: "No data received yet from sensor", 
  coords: { 
    latitude: 0,
    longitude: 0,
    altitude: 0,
    accuracy: 0,
    altitudeAccuracy: 0,
    heading: 0,
    speed: 0
  }
});

This should address the issue. I recommend obtaining the correct type from a library rather than duplicating it in the code snippet.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on Validating Several Email Addresses in a React Form using Angular 4

I need to input 50 email addresses with the same domain name (gmail.com). Currently, I am using a Reactive form but the code I have implemented is not working as expected. https://stackblitz.com/edit/angular-wfwfow If anyone could assist me with this, I ...

Triggering an event in Angular 2 after ngFor loop completes

I am currently attempting to utilize a jQuery plugin that replaces the default scrollbar within dynamic elements in Angular 2. These elements are generated using an ngFor loop, making it impossible to directly attach jQuery events to them. At some point, ...

Assign the private members of the class to the arguments of the constructor

class Bar { #one #two #three #four #five #six #seven #eight #nine #ten #eleven #twelve #thirteen #fourteen #fifteen #sixteen constructor( one, two, three, four, five, six, seven, eight, ...

I'm puzzled as to why my createDoorMethod is returning a string value instead of a number, even though I am passing it a number. Can someone help me

Currently enrolled in a web development course, I am diving into the world of Angular 2 and TypeScript. Despite following along with the video tutorial and using the same code, my implementation is not working as expected, leaving me puzzled. Here is the ...

Create TypeScript declaration files dynamically within the application's memory

Is there a way to programmatically generate declaration files using TypeScript? I know we can use tsc --declaration --emitDeclarationOnly --outFile index.d.ts, but I'm not sure how to do it in code. For example: import ts from 'typescript' c ...

Next.js is faced with a frustrating issue where images and videos are failing to display

I've been working on my Next.js 13 project with TypeScript, eslint, and Chakra UI, but I'm facing an issue with images and videos not displaying. Despite trying both the HTML <img> tag and importing Image from Chakra, the problem still per ...

Determine in React whether a JSX Element is a descendant of a specific class

I am currently working with TypeScript and need to determine if a JSX.Element instance is a subclass of another React component. For instance, if I have a Vehicle component and a Car component that extends it, then when given a JSX.Element generated from ...

Using a function as a parameter in Typescript: Anticipated no arguments, received 1.ts

I'm encountering an issue when trying to pass the doSomething function into performAction. The error message I'm receiving is Expected 0 arguments, but got 1 interface SomeInterface { name: string, id: string } function doSomethingFunction( ...

What is the process to activate a function within a component once a service method has been run?

I'm currently working on a chart configuration using amCharts, where an eventListener is registered for the bullets. This event listener then triggers another function in my chart service. My goal is to activate a method in my component as soon as th ...

Is there a way to remove a dynamically rendered component from a list?

Whenever I click a button, the same component is dynamically rendered on top of the list. But now, I need to implement a feature where users can delete any component from the list by clicking a cancel button associated with each component. Here's my ...

Exploring the differences between importing all utilities as a whole using `import * as util from "./util"` and importing a specific function only with `import {someFunction

When comparing the two options of importing from a module, which is better: import * as util from "./Util" or import {someFunction} from "./Util"? ...

Tips for scrolling ion-items vertically to the bottom and top using arrow icons in Ionic 4

I'm developing an Ionic 4 app with Angular and looking to incorporate Up and Down Arrow buttons for vertical scrolling from top to bottom and vice versa. ...

Cannot upload the same file to both Spring and Angular twice

Having trouble uploading the same file twice. However, it works fine when uploading different files. Encountering an error under the Network tab in Chrome { timeStamp: ......, status: 417 error: 'Bad Request', message: 'Required reques ...

Encountering an issue while trying to execute the command "ionic cordova build android --prod --release

Currently, I am facing an issue while trying to build my apk for deployment on the Play Store. The error message is causing a time constraint and I urgently need to resolve it. Any help or suggestions regarding this matter would be greatly appreciated. ...

Oops! An error occurred: Uncaught promise in TypeError - Unable to map property 'map' as it is undefined

Encountering an error specifically when attempting to return a value from the catch block. Wondering if there is a mistake in the approach. Why is it not possible to return an observable from catch? .ts getMyTopic() { return this.topicSer.getMyTopi ...

What is the suggested method for supplying optional parameters to a callback as outlined in the Typescript documentation?

While going through the do's and don'ts section of the Typescript documentation, I came across a guideline regarding passing optional parameters to a callback function. The example provided was: /* WRONG */ interface Fetcher { getObject(done: ( ...

Exploring the Behavior of Typescript Modules

When working with the module foo, calling bar.factoryMethod('Blue') will result in an instance of WidgetBlue. module foo { export class bar { factoryMethod(classname: string): WidgetBase { return new foo["Widget" + classname](); ...

Getting permission for geoLocation service on iOS in Ionic: A step-by-step guide

I have recently developed a social media application that utilizes geoLocation services. The app is built with Ionic 4 and has a Firebase backend. While the GeoLocation services are functioning properly on Android devices, users of iOS are not being prompt ...

Having trouble making generics work with extends in Typescript

I am facing an issue when trying to limit input to an object, but unfortunately, it is not working correctly: displayModal<T extends {[key: string]: any}, U>(component: Type<AbstractDialogComponent<T, U>>, options?: ModalDialogOption ...

Can you use TypeScript to define generic React functional components?

I am looking to add annotations to a generic in a React functional component like the following: import React, {useEffect, useState} from "react"; interface PaginatedTableProps{ dataFetcher: (pageNumber: number) => Promise<any>, columnNames: ...