React Effects

First determine whether a value can be derived directly during render. Use an effect when a component must synchronize with an external system, while carefully handling dependencies and cleanup.

In React, an Effect lets a component synchronize with something outside React, such as a browser API, timer, subscription, network connection, or third-party widget. Effects run after React has rendered and committed the component, so they are not the right tool for ordinary calculations based only on props or state.

If a value can be computed from the component's current props and state, calculate it during render instead of storing it separately and updating it in an Effect. This avoids an unnecessary render cycle and prevents duplicated state from becoming inconsistent. For example, `const fullName = firstName + " " + lastName` does not require an Effect.

An Effect is declared with `useEffect(() => { ... }, [dependencies])`. React re-runs the setup when one of the listed reactive dependencies changes. The dependency list should reflect the values from the component that the Effect reads and that can change between renders.

When synchronization needs to be stopped or reset, return a cleanup function from the Effect. React calls cleanup before re-running the Effect because dependencies changed and when the component is removed. Typical cleanup work includes unsubscribing, clearing timers, disconnecting resources, or removing event listeners.

Effects should not be used as a general mechanism for responding to every state change. Event handlers are usually more appropriate for user-triggered actions, while Effects are appropriate when rendering itself needs to synchronize with an external system.

Key points

Interview questions

When should you use `useEffect` in React?

Use `useEffect` when a component needs to synchronize with something outside React's rendering model. Examples include subscriptions, timers, browser APIs, and third-party widgets. If the logic only calculates a value from props or state, it normally belongs directly in render instead. User interactions are usually handled with event handlers.

What does the dependency array of `useEffect` do?

The dependency array tells React which reactive values used by the Effect can cause it to be synchronized again. When a dependency changes, React runs the previous cleanup and then runs the new setup. An empty array means the Effect does not depend on changing reactive values from the component. Dependencies should match the values the Effect reads that are reactive.

Why is cleanup important in an Effect?

Cleanup reverses or stops the external synchronization established by the Effect. Without it, timers, subscriptions, or event listeners can remain active after they are no longer needed. React calls cleanup before re-running an Effect after dependency changes and when the component is removed. A good Effect therefore has a clear setup and teardown relationship.

How would you refactor an Effect that calculates derived state?

First identify the source values and the value being calculated. If the calculated value can be obtained directly from current props or state, remove the extra state and Effect and calculate it during render. This reduces synchronization code and avoids an extra render caused by updating state from the Effect. If the calculation is expensive, `useMemo` may be considered for performance, but it does not replace the role of an Effect.

What is the difference between an Effect and an event handler?

An event handler is caused by a specific interaction or event, such as a button click, and is the natural place for logic directly caused by that interaction. An Effect is caused by rendering and dependency changes, and its purpose is to synchronize the component with an external system. Moving interaction-specific actions into Effects can make causality less explicit and can cause work to happen for reasons other than the original user action. Choosing between them starts with identifying what actually triggers the operation.