0

New to TypeScript, and I'm wondering how to type an axios response when saving it to a state variable?
I'm making a simple API call from App.tsx, which returns the followings object:

{data: {…}, status: 200, statusText: 'OK', headers: {…}, config: {…}, …}
config: {//////}
data: {copyright: 'Dietmar Hager', date: '2022-02-26', explanation: 'Large spiral galaxy NGC 4945 is seen nearly edge-o…xy and home to a central supermassive black hole.', hdurl: 'https://apod.nasa.gov/apod/image/2202/NGC4945-Dietmar-Eric-crop.jpg', media_type: 'image', …}
headers: {////}
request: XMLHttpRequest {///}
status: 200
statusText: "OK"
[[Prototype]]: Object

I'm accessing the data rpoperty of this object, and then setting that to state:

{copyright: 'Dietmar Hager',.....', 
hdurl: 'https://apod.nasa.gov/apod/image/2202/NGC4945-Dietmar-Eric-crop.jpg', media_type: 'image', …}
copyright: "Dietmar Hager"
date: "2022-02-26"
explanation: "Large spiral galaxy NGC 4945 ......"
hdurl: "https://apod.nasa.gov/apod/image/2202/NGC4945-Dietmar-Eric-crop.jpg"
media_type: "image"
title: "Nearby Spiral Galaxy NGC 4945"
url: "......"
[[Prototype]]: Object

Given that the response is an object, I thought I should set the initial state to an empty object, but got the following error

Property 'map' does not exist on type '{}'

Any suggestions on how to type an axios response?

Here's the project so far:

App.tsx

import React, { useEffect, useState } from 'react';
import axios, { AxiosResponse } from 'axios'

function App(): JSX.Element {


  const [ photo,setPhoto ] = useState({})


  const getData = async (): Promise<void> => {
    await axios.get('https://api.nasa.gov/planetary/apod?api_key=*********')
    .then((response: AxiosResponse) => {
      console.log(response)
      setPhoto(response.data)
    })
  }

  console.log(photo)
  useEffect(() => {
    getData()
  },[])

  return (
    <div>
      {photo.map(x => {console.log(x)})}
    </div>
  );
}

export default App;

Also occurred to me that I should set the types of each individual element of the object as an interface, but it seems a clunky way of doing things:

function App(): JSX.Element {

  interface State {
      url:string
  }

  const [ photo,setPhoto ] = useState<State>({})


  const getData = async (): Promise<void> => {
    await axios.get('https://api.nasa.gov/planetary/apod?api_key=*********')
    .then((response: AxiosResponse) => {
      console.log(response)
      setPhoto({url:response.data.url})
    })
  }
Josh Simon
  • 159
  • 1
  • 10
  • 27

1 Answers1

0

For using map you should convert your data to an array! For this you can use Object.values()

import React, { useEffect, useState } from 'react';
import axios, { AxiosResponse } from 'axios'

function App(): JSX.Element {


  const [ photo,setPhoto ] = useState({})


  const getData = async (): Promise<void> => {
    await axios.get('https://api.nasa.gov/planetary/apod?api_key=*********')
    .then((response: AxiosResponse) => {
      console.log(response)
      setPhoto(response.data)
    })
  }

  console.log(photo)
  useEffect(() => {
    getData()
  },[]);

  return (
    <div>
      {Object.values(photo).map(x => {console.log(x)})}
    </div>
  );
}

export default App;