Basics

Context-API is the global state management tool that we can use in React. When dealing with the states in different components, sharing them between the components can cause props drilling, to avoid that, we should use global state management solutions.

Props Drilling

Image 1.1

Image 1.1

The basic way of sharing data between the components in React is using the props. But when the depth of the component tree gets bigger, sharing the data between the components with props can have a negative effect on performance and also it creates unnecessary usage of props just the share data between two components.

Image 1.2

Image 1.2

Let’s say we need name state in component Z to manipulate the UI and we should collect name state from component C. To do that, name state should travel from C to Z by passing all the nested components between these two on the component tree(Image 1.2). That means we should create a callback function and use props to pass that data on each components. In this case, it doesn’t seem too bad, at first glance, but when the app gets bigger, this will create unnecessary usage and weight on the components just to pass data. And that’s called Props Drilling.

Creating and Using the Context-API

Context-API is a built-in react global state management tool that helps us avoid props drilling in our app. We don’t need to install any framework to use that, it comes within the react.

By using the Context-API, we can globally manage the states from any components without creating a props drilling. We can think of working on a shared document so that everyone who has access can edit, update, or use the data from that shared document without losing any data. Also, no one needs to share or receive updates from each other since the shared document will always keep the updates from every collaborator.

To use the Context-API, we first need to create store component. Store components will be our context component, which holds the app-wide data. Let’s call it TestContext.js

const TestContext = createContext(defaultValue)

const TestContextProvider = ({children}) => {
	const [state, setState] = useState(someValue)

	return (
		<OurContext.Provider value={state}>
			{children}
		</OurContext.Provider>
}

export default TestContextProvider

Then we need to provide TestContext to the components that we want to use the context data. To do that we need to wrap the components with our provider. The most common way is wrapping the all components in our entry point, most of the time App component(depending on your structure). By doing that, we simply tell the react that all the components rendered under the App can reach the context store, use, and manipulate the state there without needing props.

App.js

const App = () {
  return (
    <OurContextProvider>
      <OurCustomComponent/>
    </OurContextProvider>
  );
}

And then we can simply call and use the data in our custom component. To do that;

const OurCustomComponent = () => {
	const ctx = useContext(OurCustomContext) 
	// or const {state} = useContext(OurCustomContext) objec destructuring

return (
	<>
		<p>{ctx.state}</p>
	</>
}

export default OurCustomComponent

Context-API is a good alternative for global state management but it also has some downsize. We can create multiple stores for each context provider but this will cause the context hell. Also, another issue is Context-API is not good for high-frequency updates, it can have a negative effect on performance. For high-frequency updates, React-Redux is a better solution.