Skip to content
Advertisement

REACT createContext with async function return axios data

I’m creating React context but it returns a promise. In the file playlistcontext.js I’ve the following code:

import React, { useEffect } from 'react';
import YouTube from '../services/youtube';

const playlistsData = YouTube.getPlaylists();
// console.log(playlistsData);
const PlaylistsDataContext = React.createContext(playlistsData);

const PlaylistsDataProvider = (props) => {
    
    const [playlists, setPlaylists] = React.useState(playlistsData);

    useEffect(() =>{
        const playlistsData = YouTube.getPlaylists();
        console.log(playlistsData);
        setPlaylists(playlistsData);
    },[])

    return <PlaylistsDataContext.Provider value={[playlists, setPlaylists]}>{props.children}</PlaylistsDataContext.Provider>;
}

export {PlaylistsDataContext, PlaylistsDataProvider};

In the file youtube.js, that I use it like a service, I’have the code below. In this function a console.log(result.data) return me the correct data.

import axios from 'axios';
import { YOUTUBE_API } from '../config/config';

function Youtube() {

    const handleError = (resp) => {
        
        let message = '';

        switch (+resp.status) {
            case 401:
                message = resp.data.error;
                break;
            default:
                message = 'general error';
        }

        return message;
    }

    const getPlaylists = async () => {

        try {
            const result = await axios.get(YOUTUBE_API + '');
            
            return result.data;
        } catch(e) {
            return Promise.reject(handleError(e.response));
        }
        
    }

    return {
        getPlaylists
    }
}

const ytMethod = Youtube();
export default ytMethod;

then, I have a containers “tutorialcontainer.js” in which I’ve wrapped a component:

import React, {useState} from 'react';
import { PlaylistsDataProvider } from '../containers/playlistscontext';
import Tutorials from '../components/tutorials';

const TutorialsContainer = (props) => {

    return (
        <PlaylistsDataProvider>
            <Tutorials />
        </PlaylistsDataProvider>
    );
}

export default TutorialsContainer;

In the last file tutorials.js I have the component. In this file the console.log(playlist) returns me a promise.

import React, {useState, useEffect} from 'react';
import SectionBoxPlaylist from '../components/html_elements/card_playlist';
import Header from '../components/header';
import { PlaylistsDataContext } from '../containers/playlistscontext';

const Tutorials = (props) => {

    const [playlists, setPlaylists] = React.useContext(PlaylistsDataContext);

    return (
        <div className="app-container">
            <Header />
            <div className="section section-one text-center">
                <div className="section-content">
                    <div className="section-box-items">
                        {   
                            Object.keys(playlists).map((item) => {
                                return <SectionBoxPlaylist key={item} id={item} info={playlists[item]} />
                            })
                        }
                    </div>
                </div>
            </div>
        </div>
    );
}

export default Tutorials;

Can you help and explain me why? Thank you!

Advertisement

Answer

setPlaylists is called immediately after YouTube.getPlaylists().

useEffect(() => {
  const playlistsData = YouTube.getPlaylists();
  console.log(playlistsData); // playlistsData is not fetched
  setPlaylists(playlistsData);
},[])

You should be able to use .then():

YouTube.getPlaylists().then(response => {
  console.log(response);
  setPlaylists(response);
});

You can also create async function inside useEffect():

useEffect(() => {
  const getYTPlaylist = async () => {
    const playlistsData = await YouTube.getPlaylists();
    console.log(playlistsData);
    setPlaylists(playlistsData);
  }
  
  getYTPlaylist();
},[])
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement