5

I am new to React Context. I need to call the API in react context to use its data throughout my react application. Also the same API needs to be called on some CRUD operation on various component of react application.

For now I am storing API data in redux which I don't want to store.

Here is what I have tried..

context.js File

import React, { useState, createContext,useEffect } from 'react';
import {getData} from './actionMethods';

const NewContext = createContext();

function newContextProvider(props) {
    useEffect(async () => {
         const {dataValue}  = await getData()

         console.log("Data " , dataValue)    
     }, [])
     
     return (
        <NewContext.Provider
            value={{
                state: {
                    
                },
                actions: {
                    
                }
            }}
        >
            {props.children}
        </NewContext.Provider>
    );
}


const newContextConsumer = newContext.Consumer;

export { newContextProvider, newContextConsumer, newGridContext };

actionMethods.js

export function getData() {
    let config = getInstance('GET', `${prefix}/xyz/list`)
    return axios(config).then(res => res.data).catch(err => {
      console.log(err)
    })
  }

when any CRUD operation performs , I need to call the API from the context.js file to get the data from API and store in the context.

Any help would be great.

Thank You.

Xperia Reno
  • 381
  • 1
  • 9
  • 17

1 Answers1

4

First we create the Context and pass it an initial value.

In order to fetch data and keep track of the returned value, we create a state inside the component. This component will manage the fetched data and pass it in the Context Provider.

To call an async function inside useEffect we need to wrap it and call it inside useEffect callback.

export const NewContext = createContext({
    my_data: {} // Initial value
});

export const NewContextProvider = props => {
    const [my_data, setMyData] = useState({});

    useEffect(() => {
        const fetchMyData = async () => {
            const { dataValue } = await getData();

            if (dataValue) {
                setMyData(dataValue);
            } else {
                // There was an error fetching the data
            }
        };

        fetchMyData();
    }, []);

    return (
        <NewContext.Provider
            value={{
                my_data
            }}
        >
            {props.children}
        </NewContext.Provider>
    );
};

To use this Context in a component we use the useContext hook. Remember that this component needs to be wrapped by the Provider we just created.

import React, { useContext } from "react";
import { NewContext } from "./NewContext"; // The file where the Context was created

export const MyComponent = props => {
    const { my_data } = useContext(NewContext);

    return //...
};

Let me know if something is not clear.

Alvaro
  • 9,247
  • 8
  • 49
  • 76
  • thank you so much for you time. when I console `my_data` , it says undefined. the API is called perfectly. – Xperia Reno Dec 17 '19 at 08:55
  • @XperiaReno No problem at all! It looks like the data is not returning correctly from `getData`. I just copied this from the question, but lets see what it is getting. Could you log exactly what it is returning? Change the line in useEffect for this: `const dataValue = await getData(); console.log(dataValue);` – Alvaro Dec 17 '19 at 08:59
  • yes. I got the data.. the reason is we 've put `const {dataValue}`. instead we have to put `const dataValue`. and last question. when I use this context in other component after doing CRUD operation and to get the updated Data. how can I do that ?? something like action.someMethod to call the function and inside that function , the API will be automatically called and store the data ? – Xperia Reno Dec 17 '19 at 09:04
  • Great you could solve it. I'm not following your question, what do you mean by `action.someMethod`? If you are asking if a component using the Context (for example the `MyComponent` above) will re-render once the Context data changes, the answer is yes, it will re-render every time the value passed in the Context Provider changes. – Alvaro Dec 17 '19 at 09:08
  • yes.. so what I mean is . I have performed the operation called **delete** list in myComponent. so after performing operation and after getting the response from delete API , I will get the updated list. so to call the function that calls the API for getting updated list, what code should I write on the success of delete API call that will call the function that is in context and that will call the API to get updated list.. – Xperia Reno Dec 17 '19 at 09:34
  • Well, this is a complex issue which depends on the design of your app. You could for example, keep track of the server state inside a Redux store or inside a React Context that is fetched on page load. Then if you remove an item you first send a request to the server. If it succeds then you update your local store/Context. This is just an approach but I think it is worth asking a new question so you can expand the case and receive a detailed answer. – Alvaro Dec 17 '19 at 09:42
  • Yes. I have put another question. Can you see that ?? https://stackoverflow.com/questions/59372275/react-js-get-context-data-after-getting-success-on-api-call – Xperia Reno Dec 17 '19 at 10:33
  • shouldn't the await be wrapped in a try/catch or the fetchMyData() call have a catch handler ? – gaurav5430 Jan 11 '21 at 04:33