Let's grow a garden together! - Nature's useEffect.
Learn how React’s side effects mirror the natural cycles of growth, change, and renewal.

Planning a garden is no small task—every plant has its own unique needs: one may thrive in abundant sunlight, another may demand constant water, while yet another might rely on the gentle touch of the wind. Each element must be considered together, as the growth of one is never separate from the rest.
Some plants require daily water, while others need it only once a month, and some patiently wait for the seasonal rains. A few flowers open beautifully under sunlight, while others shrink away from it. The gardener doesn’t treat them all the same—each plant is tended to at its own pace, in its own rhythm.
React works much the same way with useEffect. Think of it as the gardener of your component. Some effects must run every time, like daily watering. Some run only once, like planting a seed at the start. Others wait until the right condition changes—like rain arriving after a long summer. Each effect listens, responds, and nurtures the component, just as a gardener listens to the silent needs of their plants.
For example, roses need water every single day. Instead of remembering to water them manually, the gardener might set up a system so that with the arrival of each new day, the roses are automatically refreshed with water. React gives us something similar to useEffect. If we want a particular piece of code to run every time our component renders, we place it inside useEffect without a dependency array. Just like the gardener’s daily watering system, React ensures the effect is triggered on every render.
useEffect(() => {
console.log("Watering the roses 🌹 (runs on every render)");
});
Now, not every action in a garden happens daily. Take sowing seeds, for example—you only do it once when you start the garden. The gardener doesn’t keep planting the same seed again and again. In React, this is like using useEffect with an empty dependency array []. It tells React: ‘run this effect only once, when the component first mounts, and never again.’
useEffect(() => {
console.log("🌱 Sowing the seeds (runs only once when component mounts)");
}, []);
Some flowers don’t need daily watering or one-time sowing—they wait for the sunlight to change. On a cloudy day, they stay still, but when the sun shines bright, they open up in full bloom. In React, this is like using useEffect with a dependency array. The effect doesn’t run all the time, only when a specific value changes.
useEffect(() => {
console.log(Flowers react to sunlight: ${sunlight} ☀️);
}, [sunlight]);
A small summary of what we understood so far!
| Garden Action | Frequency | React useEffect Equivalent | Example Code Trigger |
| Watering roses daily | Every single day | Runs on every render (no dependency array) | useEffect(() => {...}); |
| Sowing seeds | Only once, at the beginning | Runs once on mount ([]) | useEffect(() => {...}, []); |
| Flowers reacting to sunlight | Only when sunlight changes | Runs when dependency changes ([sunlight]) | useEffect(() => {...}, [sunlight]); |
Doesn’t this seem simple enough? A gardening task, something so natural and intuitive, mirrors how React useEffect works. By thinking of it as watering daily, sowing seeds once, or responding to sunlight changes, the logic behind dependencies suddenly feels less intimidating and more practical.
And this is just one piece of React’s powerful hook system. In our next article, we’ll step into useContext a hook that many developers both fear and love. Where useEffect is about timing and conditions, useContext is about connection: sharing values across components without having to pass props through every layer.
Stay tuned—we’ll uncover how useContext works, why it’s so useful, and how to overcome the fear around it.




