0

I have the following function:

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

I set the location here:

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

With coords interface:

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

From:

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

I want to render the data like this:

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

But I receive:

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

I can't receive any properties of the object because the object is empty {} like I stated in useState().

When I try to define the object in useState() I get an error because e.g. altitude can be a number or null.

My question is how can I add coords to dataLoc without defining it and still retrieving the object elements or defining it that some values can be a number or null?

I also tried 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:

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'.
2
  • 1
    How are you bringing in Geolocation? Commented Mar 3, 2022 at 15:34
  • added the import and showed the interface from the npm package! Commented Mar 4, 2022 at 16:55

2 Answers 2

1
+50
const [dataLoc, setDataLoc] = useState<{
  date: string;
  coords: GeoCoordinates;
}>({
  date: '', 
  coords: {} as GeoCoordinates,
});
/*
 * Your another codes
 */

//calling it everwhere you want (e.g in useEffect)
const _setLocation = () => {
  //checking location permission then
  Geolocation.getCurrentPosition(
    ({timestamp, coords}) => {
      const date = dateToString(timestamp);
      setDataLoc({date, coords});
    },
    e => console.log(e),
  );
};
/*
 * Your another codes
 */
return (
  <Text style={styles.data}>
    {dataLoc.coords?.latitude}
  </Text>
);
Sign up to request clarification or add additional context in comments.

1 Comment

I just added as GeoCoordinates and fixed the import to solve my problem!
1

You need to be explicit about the type of your state value because it can't be inferred from the init value.

For example if your state value is a number type annotation is not required.

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

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

But let't say your value can be either a number or a string. It's impossible for TS to infer that from the init value because a value can't be simultaneously a string and a number. So we we pass the type to this generic useState function.

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

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

Now going back to your specific example, when 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
  }
});

as shown in the error, this is the type that TS infers from that

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

but that doesn't represent the reality, so you'd need to define the type or get it from the library and pass 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
  }
});

That should solve the error. I'd recommend getting the correct type from the library instead of duplicating it as I did in the code snippet.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.