React Creating Context

In the last lesson, React Introduction to Context API, you learned the three steps: create, provide, read. This lesson does the first one, so we’ll create a context with createContext and get it ready for the provider and readers that come next.

🤔 What does “creating context” mean?

Creating a context just means making the empty container that will hold your shared data.

  • You call createContext() once to make a context object.
  • That object is what everything else points to, so the provider that fills it and the components that read it all refer to the same one.
  • You usually create it in its own file and export it, so any component can import it.
  • It has no real value yet. That comes from the provider later, right?

So this step is small. You’re just making the named box.

🧩 Using createContext

You make a context by calling createContext, imported from React. You can pass a default value.

import { createContext } from "react";
// create the context with a default value
export const ThemeContext = createContext("light");

Read each part.

  • We import createContext from React.
  • createContext("light") makes the context and sets "light" as its default value.
  • We export it, so the provider and any reader can import the same ThemeContext.
  • That name, ThemeContext, is what you’ll pass to the provider and to useContext later.

Name it for what it holds

Name your context after the data it carries, like ThemeContext, UserContext, or AuthContext. The capital first letter and Context suffix are the common convention, and they make the code easy to read.

🎯 The default value

The value you pass to createContext is the default. It’s used only when a component reads the context with no provider above it.

// default is "light"
export const ThemeContext = createContext("light");
// later, a component with NO provider above reads "light"
const theme = useContext(ThemeContext); // "light"

Understand when the default matters.

  • If there is a provider above the component, the reader gets the provider’s value, not the default.
  • So most of the time the provider’s value wins, and the default is just a safety net.
  • It’s also handy as documentation, since it shows the shape of value the context expects.

Don't rely on the default for real data

The default is a fallback, not where you store your actual app data. Your real, changing value comes from the provider. Set a sensible default (like "light" or null), but expect the provider to supply the live value.

📁 Putting context in its own file

A clean pattern is to create the context in its own small file and export it.

ThemeContext.js
import { createContext } from "react";
export const ThemeContext = createContext("light");

Why a separate file helps.

  • The provider component imports ThemeContext from here to fill it.
  • Every component that reads the context imports the same ThemeContext from here.
  • So there’s one source of truth, and nothing gets out of sync.

⚠️ Common Mistakes

A common mistake is creating the context inside a component, so a new one is made on every render.

// ❌ created inside a component - a brand new context on every render
function App() {
const ThemeContext = createContext("light"); // wrong place
// ...
}
// ✅ created once at the top level (module scope), outside any component
export const ThemeContext = createContext("light");
function App() {
// ...
}

Keep these in mind.

  • Don’t call createContext inside a component. Create it once at the top level of a file.
  • Don’t forget to export it, or other files can’t import the same context.
  • Don’t expect the default to hold your live data. It’s just a fallback.

✅ Best Practices

A few habits for creating context.

  • Call createContext once, at the top level of a file, not inside a component.
  • Export the context so the provider and all readers share the same object.
  • Name it clearly, like ThemeContext or UserContext.
  • Give it a sensible default that shows the expected shape, like "light" or null.

One line, then move on

Creating the context really is just that one createContext line. The interesting work, giving it a real value and reading it, happens in the provider and readers, which are the next lessons.

🧩 What You’ve Learned

  • ✅ Creating a context makes the shared container that the provider fills and readers read
  • ✅ Use createContext(defaultValue), imported from React
  • ✅ The default value is a fallback, used only when a component has no provider above it
  • ✅ Create the context once at the top level of a file, not inside a component
  • ✅ Export the context so the provider and all readers use the same object
  • ✅ Name it clearly, like ThemeContext, and give it a sensible default

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does createContext do?

    Why: createContext makes the context object itself. Filling it with a real value is the provider's job, and reading it is done with useContext.

  2. 2

    When is the default value passed to createContext actually used?

    Why: If a provider wraps the component, the reader gets the provider's value. The default is a fallback used only when there's no provider above.

  3. 3

    Where should you call createContext?

    Why: Create the context once at module scope. Calling it inside a component would make a new context on every render, which breaks sharing.

  4. 4

    Why export the context object?

    Why: Exporting it gives one source of truth. The provider and every reader import the same ThemeContext, so they all refer to the same context.

🚀 What’s Next?

Now you have a context object, but it’s still empty. Next you’ll wrap part of your app in the context’s Provider and give it a real value, so components inside can finally read shared data.

React Provider Component

Share & Connect