-1

Widgets.js

import React, {useContext} from 'react';
    import { DataContext } from '../contexts/DataContext';
    
    
    const Widgets = () => {
        const {updates} = useContext(DataContext);
        console.log(updates);
        return (
            <div className="MainWidget">
                <ul>
                    {updates.map(update => {
                        return (
                          <div>
                            <li>{update.current.condition}</li>
                            <p>{update.current.temp_c}</p>
                          </div>
                        );
                    })}
                </ul>
            </div>
        );
    }
    
    export default Widgets;

I'm mapping data from an API which is returning an error: TypeError: updates.map is not a function but its actually returning the data in the console using the console.log() function.

DataContext.js :I'm using axios to fetch data from weatherapi.com and setting the state 'updates' with 'setUpdates' function.

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

export const DataContext = createContext();

const DataContextProvider = (props) => {
    const [updates, setUpdates] = useState({});
    const url = "https://api.weatherapi.com/v1/current.json?key=931701d0de0c4d05b0b34936203011&q=London";

    useEffect(() => {
        axios.get(url)
         .then(res => {
             console.log(res.json())
             setUpdates(res.data)
         })
         .catch(err => {
             console.log(err)
         })
    })
    return (
        <div>
            <DataContext.Provider value={{updates}}>
                {props.children}
            </DataContext.Provider>
        </div>
    )
}


export default DataContextProvider;

enter image description here

2 Answers2

0

You're requesting data for only one location and the API returns you an object, not an array. You can either change your component to expect an object, or update the context provider, so it provides an array. That will looks something like:

const [updates, setUpdates] = useState([]);//note you want an array ([]) not an object ({})
 ...
let data = res.data
if(!data instanceof Array) data = [data] //put an object into array if needed
setUpdates(data)

UPDATE

In you repo make following changes:

In the DataContext you need to parse JSON response into an object, so replace

axios.get(url)
     .then(res => {
         setUpdates(res.data.current)
     })

with

axios.get(url)
     .then(res => res.json())
     .then(res => {
         setUpdates(res.current)
     })

This will mean you already have current in the provider and in the component you can access its fields directly, so you'll need to replace

 <p>{updates.current}</p>

with something like

 <p>{updates.temp_c}</p>
 <p>{updates.humidity}</p>
Nadia Chibrikova
  • 3,691
  • 1
  • 10
  • 14
-1

Not sure, but either your updates is an object, which means you can't map, or while your API is being called, that is undefined, which is why it crashes.

If your update is an object then you can do: map function for objects (instead of arrays)

If its undefined while calling API, then you can do a simple check to see if its undefined and only map when it's not.

medzz123
  • 139
  • 5