I'm not advocating for any ground breaking paradigms here, I guess my only point is that the common advice to just throw everything into Redux (global store) is bad advice. You should only put global state into your global store. The common alternative is to silo state and functionality/UI into one component. I'd argue the third alternative, taking the best of both worlds, enables far more productivity. Basically creating mini-Redux stores that are only focused on one bit of user interaction. These are far more reusable, and since they're scoped locally they eliminate a lot of edge cases (and they're composable!).
Imagine you have a React tree with a 100 node depth. You would then need to walk all the way up those 100 nodes, but using the context api you can put in context consumer at the branches of your tree where it makes sense, so instead of walking up 100 nodes you walk up 3 nodes to input into the global context.
Hope that is a reasonable high level explanation of a thing that can be complicated without experience of it.
Now, if any components you build in the future also need access to P's state, you can easily implement it as a new pure component that is a descendant of P. Since it has access to the callbacks, it will be able to update our original component C by invoking them.
With this setup, your app is basically separated into two "classes" of components, providers and consumers. Each provider holds the state and callbacks specific to itself only, which means you can easily pull out an individual provider and consumer to reuse in a new place (instead of being dependent on a global store).
The biggest benefit here is that future components can interact with P and by extension C without changing any code in P or C. Furthermore, if you want two parallel widgets with independent state, you can just create two instances of P as siblings, with C as descendants of both of them. If you wanted to do the same with a global store, you would most likely have to update your implementation to support parallel state tracking.
Another benefit is that you don't have to "clean up" the state when P is discarded. For example, if you are using a global store, and you navigate to a new page, you have to implement a callback to clear the widget state from the global store or risk loading stale state when the user navigates back. With this approach, since P has been removed from the tree, its state will be discarded along with it.
The only stuff I put in my global store is stuff that is actually relevant to my entire application. For example the user's username and preferences.