React – keep all state management in Context Provider while using an async call

I am trying to find a more elegant way to create a provider/consumer where an async call is made from the provider, but the consumer doesn’t have to manage state.

I have a context provider where I’m fetching to see if feature flags are enabled:

  const [featureFlags, setFeatureFlag] = useState({});

  async function checkFeatureFlag(someKey) {
    if (typeof featureFlags[someKey] === 'boolean') {
      return featureFlags[someKey]
    } else {
      // returns a promise
      const result = await evaluateFeatureFlag(someKey);
      
      setFeatureFlag({[someKey]: result})

      return result;
    }
  }

  return (
    <FeaturesContext.Provider value={{ checkFeatureFlag }}>
      {children}
    </FeaturesContext.Provider>
  );

In my consumer I’m trying to pass a feature flag key and determine if the flag is enabled, but only after the promise is resolved. I want all of the state to be handled from the Context Provider, so I don’t want to have to do a useEffect or useState at all in my consumer.

  const { checkFeatureFlag } = useFeaturesContext();

  const isEnabled = checkFeatureFlag('My_cool_feature');

  return isEnabled ? <div>Show feature</div> : <div>feature is hidden</div>

This will not work unless I add an await in front of checkFeatureFlag, which won’t work unless I add an async in front of the component, which is not support in React (I don’t think).

I can add a useEffect here so that I can make the async call, but then I have to add a useState to the component as well. Again, I’d like all of the state to be handled from the context, because I’m trying to create a clean API that’s easy for other engineers to use.

To summarize, I’d like a provider that makes an async call where the consumer doesn’t have to care about state management at all.