or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

actions-filtering.mdadvanced-features.mdeffect-creation.mdindex.mdmodule-setup.mdtesting.md

effect-creation.mddocs/

0

# Effect Creation and Management

1

2

Core functionality for creating and managing effects in NgRx applications, supporting both class-based and functional patterns with comprehensive configuration options.

3

4

## Capabilities

5

6

### createEffect Function

7

8

Creates effects from source functions with configuration options, supporting both class-based and functional patterns.

9

10

```typescript { .api }

11

/**

12

* Creates an effect from a source function with optional configuration

13

* @param source - Function returning an Observable

14

* @param config - Optional effect configuration

15

* @returns Effect with metadata for registration

16

*/

17

function createEffect<

18

C extends EffectConfig & { functional?: false },

19

DT extends DispatchType<C>,

20

OTP,

21

R extends EffectResult<OT>,

22

OT extends ObservableType<DT, OTP>

23

>(

24

source: () => R & ConditionallyDisallowActionCreator<DT, R>,

25

config?: C

26

): R & CreateEffectMetadata;

27

28

function createEffect<Source extends () => Observable<unknown>>(

29

source: Source,

30

config: EffectConfig & { functional: true; dispatch: false }

31

): FunctionalEffect<Source>;

32

33

function createEffect<Source extends () => Observable<Action>>(

34

source: Source & ConditionallyDisallowActionCreator<true, ReturnType<Source>>,

35

config: EffectConfig & { functional: true; dispatch?: true }

36

): FunctionalEffect<Source>;

37

38

function createEffect<

39

Result extends EffectResult<unknown>,

40

Source extends () => Result

41

>(

42

source: Source,

43

config?: EffectConfig

44

): (Source | Result) & CreateEffectMetadata;

45

46

type FunctionalEffect<

47

Source extends () => Observable<unknown> = () => Observable<unknown>

48

> = Source & FunctionalCreateEffectMetadata;

49

50

interface FunctionalCreateEffectMetadata extends CreateEffectMetadata {

51

'__@ngrx/effects_create__': EffectConfig & { functional: true };

52

}

53

54

interface CreateEffectMetadata {

55

'__@ngrx/effects_create__': EffectConfig;

56

}

57

```

58

59

**Usage Examples:**

60

61

```typescript

62

import { Injectable, inject } from "@angular/core";

63

import { createEffect, Actions, ofType } from "@ngrx/effects";

64

import { map, switchMap, catchError } from "rxjs/operators";

65

import { of } from "rxjs";

66

67

// Class-based effect

68

@Injectable()

69

export class BookEffects {

70

constructor(private actions$: Actions) {}

71

72

loadBooks$ = createEffect(() =>

73

this.actions$.pipe(

74

ofType(BookActions.loadBooks),

75

switchMap(() =>

76

this.bookService.getBooks().pipe(

77

map(books => BookActions.loadBooksSuccess({ books })),

78

catchError(error => of(BookActions.loadBooksFailure({ error })))

79

)

80

)

81

)

82

);

83

84

// Non-dispatching effect

85

logBookActions$ = createEffect(() =>

86

this.actions$.pipe(

87

ofType(BookActions.loadBooksSuccess),

88

map(action => console.log('Books loaded:', action.books))

89

),

90

{ dispatch: false }

91

);

92

}

93

94

// Functional effect

95

export const loadBooksEffect = createEffect(

96

(actions$ = inject(Actions), bookService = inject(BookService)) =>

97

actions$.pipe(

98

ofType(BookActions.loadBooks),

99

switchMap(() =>

100

bookService.getBooks().pipe(

101

map(books => BookActions.loadBooksSuccess({ books })),

102

catchError(error => of(BookActions.loadBooksFailure({ error })))

103

)

104

)

105

),

106

{ functional: true }

107

);

108

109

// Effect with custom error handling disabled

110

export const customErrorHandlingEffect = createEffect(

111

() => actions$.pipe(

112

ofType(SomeActions.customAction),

113

switchMap(() =>

114

someService.riskyOperation().pipe(

115

map(result => SomeActions.success({ result })),

116

// Custom error handling

117

catchError(error => {

118

console.error('Custom error handling:', error);

119

return of(SomeActions.failure({ error }));

120

})

121

)

122

)

123

),

124

{ useEffectsErrorHandler: false }

125

);

126

```

127

128

### Effect Configuration

129

130

Configuration interface for customizing effect behavior.

131

132

```typescript { .api }

133

interface EffectConfig {

134

/** Whether the effect should dispatch actions (default: true) */

135

dispatch?: boolean;

136

/** Whether this is a functional effect (default: false) */

137

functional?: boolean;

138

/** Whether to use the effects error handler (default: true) */

139

useEffectsErrorHandler?: boolean;

140

}

141

```

142

143

**Configuration Options:**

144

145

- **`dispatch`**: When `false`, the effect won't dispatch actions to the store (useful for side effects like logging, navigation, etc.)

146

- **`functional`**: Must be `true` for functional effects created outside of classes

147

- **`useEffectsErrorHandler`**: When `false`, disables automatic error handling, allowing custom error handling strategies

148

149

### Effect Metadata

150

151

Metadata interface attached to created effects for runtime processing.

152

153

```typescript { .api }

154

interface CreateEffectMetadata {

155

/** Internal marker for NgRx effects system */

156

'__@ngrx/effects_create__': EffectConfig;

157

}

158

159

/**

160

* Extract effect metadata from effect instances

161

* @param instance - Effect instance to extract metadata from

162

* @returns Array of effect metadata

163

*/

164

function getEffectsMetadata<T>(instance: T): Array<{

165

propertyName: string;

166

dispatch: boolean;

167

useEffectsErrorHandler: boolean;

168

}>;

169

```

170

171

### Advanced Effect Patterns

172

173

**Conditional Effects:**

174

175

```typescript

176

loadUserData$ = createEffect(() =>

177

this.actions$.pipe(

178

ofType(UserActions.loadUser),

179

switchMap(action =>

180

this.authService.isAuthenticated$.pipe(

181

switchMap(isAuthenticated =>

182

isAuthenticated

183

? this.userService.getUser(action.userId).pipe(

184

map(user => UserActions.loadUserSuccess({ user }))

185

)

186

: of(UserActions.loadUserFailure({ error: 'Not authenticated' }))

187

)

188

)

189

)

190

)

191

);

192

```

193

194

**Debounced Search Effect:**

195

196

```typescript

197

search$ = createEffect(() =>

198

this.actions$.pipe(

199

ofType(SearchActions.search),

200

debounceTime(300),

201

distinctUntilChanged(),

202

switchMap(action =>

203

this.searchService.search(action.query).pipe(

204

map(results => SearchActions.searchSuccess({ results })),

205

catchError(error => of(SearchActions.searchFailure({ error })))

206

)

207

)

208

)

209

);

210

```

211

212

**Non-dispatching Effect for Side Effects:**

213

214

```typescript

215

saveToLocalStorage$ = createEffect(() =>

216

this.actions$.pipe(

217

ofType(PreferencesActions.updatePreferences),

218

tap(action => {

219

localStorage.setItem('preferences', JSON.stringify(action.preferences));

220

})

221

),

222

{ dispatch: false }

223

);

224

```