It's much easier to be reactive than proactive. A reactive person looks at what already happened and tries to make sense out of it - they're always playing catch-up. A proactive person needs to understand the rules beforehand so well that they can anticipate the possible scenarios that may happen.
This is why so many developers are re-active learners. For example, they'll first be given a problem or coding task, then they'll google to figure out the syntax, concepts, and usually code with trial and error until it appears to work (i.e. "coding by coincidence"). It's a very re-active approach, and it suffices for an average programmer.
The problem is that a re-active learner will always be a re-active problem solver because before you can solve the problem, you need to first understand it. This means you need to learn the concepts involved. Furthermore, if you haven't learned the concepts yet, you can't know how the system will react, which means it will likely react in ways you didn't intend. For example, a developer who never learned about concurrency or scalability will be in for a big surprise when their procedures start running in production with multiple users. Such an error can sound very cryptic, especially if "it works on my machine", but randomly fails in production. Instead of designing their code proactively to deal with the problem (where such a solution would be much cheaper), they'll have to try to reactively first learn what happened, and then hope that it's still solvable.
Therefore, a good long-term approach is to not just reactively google coding questions as you come across them, but to also proactively read the actual books and language specifications themselves. That way, you know before hand what to expect from the technology, without waiting for it to do something intentional - when learning the solution may be too late.