Modern React, with hooks and functional components, solves the problem posed in the article by choosing option 2, lift the state up. The hypothetical problem (change the avatar background when the “working” light is on) is a non-issue. You wouldn’t add an event listener for the light’s state change, you’d simply pass the “isWorking” prop to both the light and the avatar, and they would each render based on the value of “isWorking”. There is no reason for one component to know about the other; they don’t actually do anything except sit there and look pretty, correctly.
The UI is always backed by a data model. The more explicitly you express that model—by keeping it all in one tree like Redux does, for instance—the simpler your UI becomes to reason about. React won’t (can’t) stop you from doing bad things like hitting random services when a component loads, but its design, especially recently, guides you away from that pitfall.