Set the data in React Context from asynchronous API call
Asked Answered
T

1

30

I am trying to initialize a custom React context with data from back end, using a GET API request. However, the context is loaded before the API call finishe the data fetching.

What I've tried is to use a consumer to send data to the child component but I can only access the default value of the context which is set then the context is created.

Here is how I am trying to set my context data

import React, {useState,useEffect} from "react";
import {callAffiliateApi} from "./services/affiliateService/transactionContext";

export const AffiliateContext = React.createContext("Raaaaaaaaaaaa");

export const AffiliateProvider  = ({children}) => {

  const [data, setData] = useState(null);
  useEffect(()=> {
    async function fetchData() {
      const newText = await callAffiliateApi();
      setData(newText)
    };fetchData()
  },[])

  console.log("Data in the context", data);
  if(data != null){
    return (
      <AffiliateContext.Provider value={data}>
        {children}
      </AffiliateContext.Provider>
    )}
  else {
    return (
      <AffiliateContext.Provider value={"Loading..."}>
        {children}
      </AffiliateContext.Provider>)
  }

}


And here is how I'm trying to access it in the child component

import {AffiliateContext} from "../../../../AffiliateContext";

class Profile extends Component {


  constructor(props) {
    super(props);
    this.state = {
      text: this.props.text,
      user: this.props.user,

    }

  }

  render() {
    return (
    <AffiliateContext.Consumer>
      {data =>
        <div>
        {data}
      </div>}
    </AffiliateContext.Consumer>
      )
  }
}
export default Profile;

However, the only thing that gets displayed in the page is "Raaaaaaa", the default value of the component. How can I make the child component wait until the data finishes fetching from the API request?

Triiodomethane answered 2/10, 2019 at 8:23 Comment(6)
Did you used AffiliateProvider in your index.js or app.js?Arequipa
None of them. I just want to access the context in this class.Triiodomethane
You need to do this.Arequipa
You are exporting your AffiliateProvider component, so you need to use it in somewhere before you access in any child components. For example you need to wrap jsx in your App.js with AffiliateProvider. Something like ` render() { return ( <AffiliateProvider> <div> Content of your jsx </div> </AffiliateProvider> ); } `Arequipa
Can't I just add access it in the render of my Child component?Triiodomethane
I dont think you can access, can you try my suggestion?Arequipa
S
36

try to use useContext its cleaner and try not to use the async inside the useEffect!

their related issues

import React, { useState,useEffect,useContext } from "react";
import { callAffiliateApi } from "./services/affiliateService/transactionContext";

const Context = React.createContext({});
const AffiliateContext = init => useContext(Context);

export const AffiliateProvider  = ({children}) => {

  const [data, setData] = useState(null);
  const [loading,setLoading]=useState(false);

  const getAffiliates = async ()=>{
    setLoading(true)
    const newText = await callAffiliateApi();
    setData(newText)
    setLoading(false)
  }

  useEffect(()=> {
    getAffiliates()
  },[])


    return (
      <AffiliateContext.Provider value={{loading,list:data}}>
        {children}
      </AffiliateContext.Provider>
    )
}
Secant answered 2/10, 2019 at 9:0 Comment(5)
There is no such thing as useReactContext.... did you mean useContext?Cirrhosis
I believe it was a simple mis-spell of React.useContext()Vortumnus
The async function originally created in useEffect was perfectly ok. Using it outside like this requires it be wrapped in useCallback.Bueno
I am curious about the init => useContext(Context); part someone knows why is it necessary? Normally it would be written like this: const AffiliateContext = React.createContext({});Headreach
please define getAffiliates fn inside the useEffect callback or wrap it in a useCallback hook otherwise this may introduce bugs.Crews

© 2022 - 2024 — McMap. All rights reserved.