Learning new technology, again – Angular services vs. React hooks

close up of golden bait

Every four or five years in my career, I need to learn a new technology or coding framework. This time around, after learning AI prompting, harnesses for LLMs, and anything else to do with AI; I find my self needing to learn React after being away from coding for nearly three years (management does that to you).

Most recently I was using Angular. As I approach React, I am using my Angular knowledge to help me understand React. It’s not always a perfect fit. I find myself learning React hooks and thinking they were like Angular services. That’s only partially right.

I find I cement things in my head better when I write them down. If I write them down here I can easily refer to them later, plus you can benefit from it as well. Here are my notes on the similarities and differences between the two.

React Hooks vs Angular Services

They solve overlapping problems (sharing logic, managing state, handling side effects) but through fundamentally different mechanisms. Let me break it down.

The Core Similarity

Both exist to extract logic out of components so it can be reused and tested independently. Without them, you’d end up duplicating state management, API calls, and side effects across every component.

How They Actually Work

Angular Services are singleton classes managed by Angular’s dependency injection system. You define a class with @Injectable(), register it with a provider, and Angular hands the same instance to every component that asks for it via the constructor.

@Injectable({ providedIn: 'root' })
export class UserService {
  private user = new BehaviorSubject<User | null>(null);
  user$ = this.user.asObservable();

  setUser(user: User) { this.user.next(user); }
}

// In a component
constructor(private userService: UserService) {}

React Hooks are plain functions that tap into React’s rendering lifecycle. They’re called inside components (or inside other hooks) and re-run on every render. There’s no DI container, no singleton — each component gets its own isolated state.

function useUser() {
  const [user, setUser] = useState(null);
  return { user, setUser };
}

// In a component
const { user, setUser } = useUser();

Key Differences

Instance model. An Angular service is one shared object across the app (by default). A custom hook creates fresh state per component that calls it — if two components both call useUser(), they each get their own user state. To share state across components in React, you need Context, a state library (Redux, Zustand), or lifting state up.

Lifecycle coupling. Hooks are tied to the render cycle — they run top-to-bottom on every render, and rules like “only call hooks at the top level” exist because React tracks them by call order. Services have no such coupling; they’re just objects that live as long as their injector does.

Side effects. Angular services typically lean on RxJS observables for async work and reactive streams. Hooks use useEffect for side effects and either local state or external stores for reactive data. Both can wrap HTTP calls, websockets, etc., but the mental model differs — streams vs. effects-that-run-after-render.

Dependency injection. Angular has a real DI system with hierarchical injectors, providers, and tokens. React has no built-in DI; Context is the closest equivalent and is much lighter.

When the Analogy Breaks Down

If you think “hook = service,” you’ll get tripped up by state sharing. A custom hook that wraps useState is not a singleton — calling it from two components gives you two independent states. The React equivalent of a stateful Angular service is usually Context + a hook together: the Context provides the shared instance, and the hook is the ergonomic API for consuming it.

A Rough Mental Mapping

A custom hook is closer to a mixin or composition function than a service. If you’ve used Vue 3’s composables, those are a much tighter analog to React hooks than Angular services are. The shared-singleton behavior of an Angular service maps better to React Context (optionally wrapped in a hook) or an external store.

So: similar goals (reuse logic, separate concerns), quite different mechanisms (DI singletons vs. render-time functions).

, ,

Leave a Reply