Skip to main content

Effects

Effects represent side effects in TCA. They allow reducers to interact with the outside world, such as making API calls, reading from disk, or starting timers, while keeping the reducer logic pure and testable.

The Effect Type

The Effect type is a wrapper around asynchronous operations that can emit actions:
Effect.swift
Source: Effect.swift:5-24

Creating Effects

Effect.none

When no side effect is needed:
Source: Effect.swift:46-49

Effect.run

The primary way to create effects with async/await:
Source: Effect.swift:92-136
Effect.run automatically captures dependencies and provides a send function for emitting actions back into the system.

Effect.send

Immediately emit a single action:
Source: Effect.swift:138-149
Avoid using Effect.send to share logic between actions. Instead, extract shared logic into helper functions or use proper action composition.

The Send Type

The Send type allows effects to emit actions back into the system:
Effect.swift
Source: Effect.swift:196-231

Using Send

Send implements callAsFunction, so you call it like a function: send(.action) instead of send.send(.action).

Effect Patterns

Async Sequences

Stream values from async sequences:

Long-Running Effects

Error Handling

Use the catch parameter to handle errors:

Task Priority

Specify priority for effects:

Combining Effects

Merge

Run multiple effects concurrently:
Source: Effect.swift:236-294

Concatenate

Run effects sequentially:
Source: Effect.swift:296-361

Cancellation

Effects are automatically cancelled when:
  • The store is deallocated
  • The view disappears (if using .task { await store.send(.task).finish() })
  • You explicitly cancel them

Manual Cancellation

Use cancellation IDs to manually cancel effects:

Cancel All Effects

Testing Effects

Exhaustive Testing

TestStore requires you to assert on all effects:

Non-Exhaustive Testing

For flexibility in tests:

Debouncing and Throttling

Debounce

Delay effect execution until input stops:

Throttle

Limit effect execution frequency:

Effect Animations

Send actions with animations:

EffectOf Type Alias

Use EffectOf for less verbose type signatures:
Effect.swift
Source: Effect.swift:39

Best Practices

1

Keep Effects Focused

Each effect should do one thing. Use .merge() to combine multiple focused effects:
2

Always Handle Errors

Use the catch parameter or do-catch blocks:
3

Use Cancellation IDs

Always provide cancellation IDs for long-running effects:
4

Test All Effects

Use TestStore to verify effects emit the expected actions:
5

Check for Cancellation

Respect cancellation in long-running effects:

Common Pitfalls

Escaping Send: Don’t escape the send function from Effect.run:
Unhandled Errors: Effects that throw without a catch handler will trigger runtime warnings:
  • Reducers - Where effects are returned
  • Testing - Testing effects with TestStore
  • Dependencies - Injecting dependencies into effects
  • Store - How effects are executed