How to initialize context only once at startup in React

Viewed 2449

I'm relatively new to React. I have a set of data that needs to be retrieved once and only once from the server, at start-up. The data is then displayed in my Footer component which is in App.js. I thought that useContext() might be the best way to go, but can't quite figure it out.

The code for initializing the data (an object) is something like this:

 axios.get('/url/to/get/data')
            .then((response) => {
                const myData = response.data.mydata;
                setMyData({ key1: myData.field1, key2: myData.field2, key3: myData.field3 });

            });

Right now, setMyData is a state, which sets the value of the object (which is constructed from various fields that were returned from the Axios call.

How do I initialize the context with this value.

I then have a Footer component, so I imagine I want to do something like this

<context.Provider>
   <Footer>
</context.Provider>

If useContext isn't the way to go, I'm open to idea. Essentially, looking for a singleton, that is initialized once, which the Footer component can than retrieve and render for every page.

1 Answers

You should define your context, and initialize it in a one-time useEffect. once it's loaded, all the children will be able to access the context using useContext

The "Trick" here is to use a useEffect with no dependencies, causing it to run only once (As long as its parent is not re-rendering)

In this example I'm using the context on the direct child (Main), but it can be used on a deeper level.

// initialize the context
const MyContext = React.createContext();

function App() {
  const [myData, setMyData] = React.useState(null);

  // Load your data once
  React.useEffect(() => {
    axios.get('/url/to/get/data')
            .then((response) => {
                const myData = response.data.mydata;
                setMyData({ key1: myData.field1, key2: myData.field2, key3: myData.field3 });
            });
  }, []);

  // Render the Provider and the app tree
  return (
    <MyContext.Provider value={myData}>
      <Main />
    </MyContext.Provider>
  );
}

// Consumer
function Main() {
  const myData = useContext(MyContext);
  if (!myData) {
    return <div>Loading...</div>;
  }

  return (
    <div>{myData}</div>
  );
}

Related