16

The new React Context API is amazing, however I seem to be always hacking my way around accessing it outside of a React component.. When you are inside a React function component or a React class component everything is great, however when you need to read or reset a value from the context (for example due to an async operation that happens in a fetch function) there is no easy way to do it..

So, is there a way to access the values in React Context Consumer outside a react component?

Later edit: I have inherited a Redux based project and slowly transition out of it. In the action creators, I have a logout function that purges the contents of the store:

export const logoutRequest = () => dispatch => {
  navigate('Welcome')
  // Reset apollo data
  client.resetStore()
  persistor.purge()
  // Reset context api data HERE
  //
}

I could easily create a consumer in the component that calls the logout request, but that happens in 3 different components and I wouldn't want to duplicate the code there..

4
  • 4
    Could you provide any example? It is not very clear, why you should access it outside the component. Commented Aug 27, 2019 at 19:27
  • What exactly would accessing it outside of a component mean, though? It's useless without a provider, in the form of an ancestor component. So... outside of a component would mean accessing a context without a provider, which would get you... what, exactly? Commented Aug 27, 2019 at 19:35
  • Can you place your fetch function inside the component that owns the context provider? Or make the context an object, and provide setter functions to alter any necessary state? I just can't think of many situations in a React app where it's necessary to have code outside components, it definitely shouldn't be happening often. If you can post the code for some components where you're experiencing this, we can give you more specific advice. Commented Aug 27, 2019 at 19:38
  • Added more specific example.. However, I think the use case is less important here.. Commented Aug 28, 2019 at 21:36

3 Answers 3

5

You will eventually call logoutRequest() in a component right? If you don't want to duplicate code you could create a custom hook:

const useLogout = () => {
  const resetContext = React.useContext(SomeContext);
  const logoutRequest = () => dispatch => {
    navigate('Welcome');
    client.resetStore();
    persistor.purge();
    resetContext();
  };
  return logoutRequest;
}

Then you can call const logoutRequest = useLogout() in your component. You can do similar thing for asynchronous operations too.

Sign up to request clarification or add additional context in comments.

Comments

1

React context is available only when the UI is available. This means that on background tasks you can't access it. But that doesn't mean that you can't access it "outside" of components.

I'll give an example where you can and can't use it outside a component:

  • Not possible: You have a scheduled background task (using OS mechanism) to do some work (maybe fetch something), usually what happens is that the OS wakes up only a part of the app (assuming the app is in quit state) that handles the background task so that the UI will not be loaded (and interfere with what the user is currently doing) - so here the context won't be available
  • Possible: You have a web socket that listens to events from the server (maybe a chat) and when an event arrives you wish to update the context. This is possible because of the fact that web sockets cannot run in the background (when the UI is ditched by the user/system - quit state) in react native (specifically). The way to do it is to wrap the socket event handlers with a class and initialize it with context dispatch function (saved as a private property of the class). In the same scope the handlers can access this private property to update the context.

A deeper explanation for background states:

You should separate between 3 background states

  1. Quit - the app wasn't open ever (since last phone boot) or was ditched by the system to free some resources. In this state no code is allowed to execute by the app, only if it is called by the system (e.g. scheduled task).
  2. Background - The app was opened but lost the user's focus (switched to another app for example). The UI is still in memory and available (including the context) and all app's code can continue running. On iOS, this state is not possible, on Android this is possible for a limited time, usually after that the OS will quit the app.
  3. Foreground - The app open and is in the user's focus. Almost everything is possible here.

Comments

0

No, you can't. The only way to update context it would be change the value sent to the Context.Provider.

For async actions to would usually save the result in a root component(or the component where the provider is rendered) and change that value that is sent. Or you could make a function in the context as show here https://reactjs.org/docs/context.html#updating-context-from-a-nested-component

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.