Context solves a problem you shouldn't have in the first place. Most of the time the answer isn't another provider — it's a sharper type.
The smell
You're threading the same prop through four components. Instinct says: lift it to Context. Stop.
Why this happens
Prop drilling is almost always a symptom of a type that's too wide. You're passing a user object down five layers because every child "might" need a different field. That's a signal, not a destination.
Discriminated unions, not providers
type ViewState =
| { kind: "loading" }
| { kind: "empty" }
| { kind: "ready"; user: User; tasks: Task[] };
Suddenly the child doesn't need to care about the whole tree — it only sees the shape it actually needs. The compiler enforces it. The props list shrinks. Context becomes unnecessary.
If you can narrow it with a type, you don't need to widen it with a provider.
When context is actually right
Theme. Locale. An auth session that really is tree-wide. That's it. Three things.