React Data – Data is Fetched, then Disappears

I have a Context & Provider that fetches user details, adds them to an object, and stores it in both a state variable and sessionStorage.

My goal is to provide this data to any widget that needs it without having to send it down via props.

I’ve tried to create a method whereby the userData can be fetched on demand simply by accessing userData – the API call is made automatically when/if necessary.


UserDataProvider.jsx:

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

const UserContext = createContext({})

export const theUser = () =>  useContext(UserContext)

const default_info = {
                            name: null,
                            age: null,
                            hobbies: [],
                        }


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


    const [ userData, setUserData ] = useState(getUserData())

    //gets user state from session storage OR a set of defaults OR from the server
    async function getUserData(){
        var data = JSON.parse(sessionStorage.getItem("userData"))
        if (data == "undefined" || data  == null){
           console.log("no data in session - fetching from server")
           data = await FetchUserData()
           return data 
        }
    
        console.log("Found data")
        console.table(data)
        return data


    }

    async function FetchUserData(){
        var body_json = {"getinfo": 1}
        try{
            await axios.post('/api/user_info', {
                headers: {
                    'Content-type':'application/json', 
                    'Accept':'application/json',
                    withCredentials: true
                },
                body: JSON.stringify(body_json)
            }).then((response) => {
                if (response.statusText == "OK"){
                    var userDataObject = {
                        name:   response.data['name'],
                        age:    response.data['savings'],
                        hobbies:  response.data['hobbies'],
                    }
                    
                    setUserData(userDataObject)
                    sessionStorage.setItem('userData', JSON.stringify(userDataObject))
                    return userDataObject
                }
                else return null

            });  
    
        } catch(error){
            console.error(error)
            return null
        }
    }

    const accessibleObjects = { 
       userData

    }


    return (
        <UserContext.Provider value={accessibleObjects}>
            { children }
        </UserContext.Provider>
    )
}

I have also wrapped components in the app…


main.jsx:

import { UserDataProvider } from './context/UserDataProvider.jsx';

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <AuthProvider>
      <UserDataProvider>
        <Router >
          <App />
        </Router>
      </UserDataProvider>
    </AuthProvider>
  </React.StrictMode>,
)

I can see the data being found in the console.

[vite] connecting...

client:614 [vite] connected.

UserDataProvider.jsx:36 Found data

UserDataProvider.jsx:37 

(index) Value
name    dave                            
age     35
hobbies     {…} {…} {…} {…} {…} {…} {…}
Object

...

However, it never gets used!

For example, the following widget will cause the data to be loaded (I can see it happen in the console), but when I access userData.name, nothing is there.

I get

Username is

in the body.



import { theUser } from '../context/UserProvider.jsx'

const ExampleComponent = () => {

   const { userData } = theUser()

   return(
    <>
    <h1>Username is {userData.name}</h1>
    </>

   )

}
export default ExampleComponent

I’m sure I’m missing something crucial – I fight with this a lot.

Can someone help me understand the intended way to manage data like this?