Say context doesn't exist, and you have a branch of components A -> B -> C, if C depends on some state in A, B would have to have a dependency on that state too. And you'd need some boilerplate code in B that reads the props from A, and passes them to C.
If you want to use C in a different context, say A -> D -> C, then that boilerplate code needs to exist in D as well.
With larger apps, containing large component trees, the amount of this boilerplate prop-passing you need to do starts to get excessive. It's not uncommon to see components read 14 props from their parent, use one of them, and pass 13 to their child(ren).
Until now, this problem has been solved by using data stores that inject state anywhere in the tree that they please. Context is an alternative to that.
It's always existed, just now it has a new API. I have no idea what was wrong with the old one. Nobody seems to have properly explained it anywhere, the docs just make condescending suggestions not to use it without reasoning. I think I saw an arcane tweet once explaining that certain things may not have re-rendered properly when using the old API or something...