or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

action-generation.mdcomponent-store.mdcontainer-components.mddata-services.mdeffect-generation.mdentity-management.mdfeature-generation.mdindex.mdngrx-push-migration.mdreducer-generation.mdselector-generation.mdstore-setup.mdutility-functions.md

effect-generation.mddocs/

0

# Effect Generation

1

2

NgRx effect generation schematic that creates side effect classes for handling asynchronous operations and external interactions in NgRx applications. Effects listen for actions, perform side effects like HTTP requests, and dispatch new actions based on the results.

3

4

## Capabilities

5

6

### Effect Schematic

7

8

Generates NgRx effect classes using createEffect() with proper action filtering and error handling.

9

10

```bash

11

# Basic effect generation

12

ng generate @ngrx/schematics:effect User

13

14

# Effect with creator functions

15

ng generate @ngrx/schematics:effect User --creators

16

17

# Root-level effect

18

ng generate @ngrx/schematics:effect User --root

19

```

20

21

```typescript { .api }

22

/**

23

* Effect schematic configuration interface

24

*/

25

interface EffectSchema {

26

/** Name of the effect class (typically entity or feature name) */

27

name: string;

28

/** Path where effect files should be generated */

29

path?: string;

30

/** Angular project to target */

31

project?: string;

32

/** Generate files without creating a folder */

33

flat?: boolean;

34

/** Group effect files within folders */

35

group?: boolean;

36

/** Module file to register effects in */

37

module?: string;

38

/** Generate as feature effect */

39

feature?: boolean;

40

/** Generate as root effect */

41

root?: boolean;

42

/** Generate minimal effect setup */

43

minimal?: boolean;

44

/** Use creator functions */

45

creators?: boolean;

46

}

47

```

48

49

### Basic Effect Generation

50

51

Creates effect classes with common patterns for API calls and side effect management.

52

53

```typescript

54

// Generated effect class

55

import { Injectable } from '@angular/core';

56

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

57

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

58

import { of } from 'rxjs';

59

import * as UserActions from './user.actions';

60

import { UserService } from './user.service';

61

62

@Injectable()

63

export class UserEffects {

64

65

loadUsers$ = createEffect(() =>

66

this.actions$.pipe(

67

ofType(UserActions.loadUsers),

68

switchMap(() =>

69

this.userService.getUsers().pipe(

70

map(users => UserActions.loadUsersSuccess({ users })),

71

catchError(error => of(UserActions.loadUsersFailure({ error })))

72

)

73

)

74

)

75

);

76

77

createUser$ = createEffect(() =>

78

this.actions$.pipe(

79

ofType(UserActions.createUser),

80

switchMap(({ user }) =>

81

this.userService.createUser(user).pipe(

82

map(createdUser => UserActions.createUserSuccess({ user: createdUser })),

83

catchError(error => of(UserActions.createUserFailure({ error })))

84

)

85

)

86

)

87

);

88

89

updateUser$ = createEffect(() =>

90

this.actions$.pipe(

91

ofType(UserActions.updateUser),

92

switchMap(({ user }) =>

93

this.userService.updateUser(user).pipe(

94

map(updatedUser => UserActions.updateUserSuccess({ user: updatedUser })),

95

catchError(error => of(UserActions.updateUserFailure({ error })))

96

)

97

)

98

)

99

);

100

101

deleteUser$ = createEffect(() =>

102

this.actions$.pipe(

103

ofType(UserActions.deleteUser),

104

switchMap(({ id }) =>

105

this.userService.deleteUser(id).pipe(

106

map(() => UserActions.deleteUserSuccess({ id })),

107

catchError(error => of(UserActions.deleteUserFailure({ error })))

108

)

109

)

110

)

111

);

112

113

constructor(

114

private actions$: Actions,

115

private userService: UserService

116

) {}

117

}

118

```

119

120

**Usage Examples:**

121

122

```bash

123

# Generate user effects

124

ng generate @ngrx/schematics:effect User --creators

125

126

# Generate product effects with custom path

127

ng generate @ngrx/schematics:effect Product --path=src/app/catalog --creators

128

129

# Generate root-level auth effects

130

ng generate @ngrx/schematics:effect Auth --root --module=app.module.ts

131

```

132

133

### Non-Dispatching Effects

134

135

Effects that perform side effects without dispatching actions.

136

137

```typescript

138

// Non-dispatching effect example

139

@Injectable()

140

export class LoggingEffects {

141

142

logActions$ = createEffect(() =>

143

this.actions$.pipe(

144

tap(action => console.log('Action dispatched:', action))

145

),

146

{ dispatch: false }

147

);

148

149

saveToLocalStorage$ = createEffect(() =>

150

this.actions$.pipe(

151

ofType(UserActions.updateUserPreferences),

152

tap(({ preferences }) => {

153

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

154

})

155

),

156

{ dispatch: false }

157

);

158

159

constructor(private actions$: Actions) {}

160

}

161

```

162

163

### Error Handling Patterns

164

165

Comprehensive error handling strategies in generated effects.

166

167

```typescript { .api }

168

/**

169

* Error handling patterns for effects

170

*/

171

interface ErrorHandlingPatterns {

172

/** Basic catch and dispatch error action */

173

basicCatch: 'catchError(error => of(ErrorAction({ error })))';

174

/** Retry with exponential backoff */

175

retryWithBackoff: 'retryWhen(errors => errors.pipe(delay(1000), take(3)))';

176

/** Handle specific error types */

177

specificErrors: 'catchError(error => error.status === 404 ? of(NotFoundAction()) : of(ErrorAction({ error })))';

178

}

179

```

180

181

```typescript

182

// Advanced error handling

183

loadUsersWithRetry$ = createEffect(() =>

184

this.actions$.pipe(

185

ofType(UserActions.loadUsers),

186

switchMap(() =>

187

this.userService.getUsers().pipe(

188

retry(3),

189

map(users => UserActions.loadUsersSuccess({ users })),

190

catchError(error => {

191

// Log error for monitoring

192

console.error('Failed to load users:', error);

193

194

// Handle different error types

195

if (error.status === 404) {

196

return of(UserActions.noUsersFound());

197

} else if (error.status === 403) {

198

return of(UserActions.unauthorizedAccess());

199

} else {

200

return of(UserActions.loadUsersFailure({

201

error: error.message || 'Unknown error occurred'

202

}));

203

}

204

})

205

)

206

)

207

)

208

);

209

```

210

211

### Router Integration Effects

212

213

Effects that interact with Angular Router for navigation.

214

215

```typescript

216

// Router integration effects

217

import { Router } from '@angular/router';

218

219

@Injectable()

220

export class RouterEffects {

221

222

navigateToUser$ = createEffect(() =>

223

this.actions$.pipe(

224

ofType(UserActions.selectUser),

225

tap(({ userId }) => {

226

this.router.navigate(['/users', userId]);

227

})

228

),

229

{ dispatch: false }

230

);

231

232

redirectAfterLogin$ = createEffect(() =>

233

this.actions$.pipe(

234

ofType(AuthActions.loginSuccess),

235

tap(() => {

236

this.router.navigate(['/dashboard']);

237

})

238

),

239

{ dispatch: false }

240

);

241

242

constructor(

243

private actions$: Actions,

244

private router: Router

245

) {}

246

}

247

```

248

249

### Feature Effect Registration

250

251

Automatic registration of effects in Angular modules.

252

253

```typescript

254

// Generated module registration

255

import { EffectsModule } from '@ngrx/effects';

256

import { UserEffects } from './user.effects';

257

258

@NgModule({

259

imports: [

260

EffectsModule.forFeature([UserEffects])

261

]

262

})

263

export class UserModule {}

264

265

// Root module registration

266

@NgModule({

267

imports: [

268

EffectsModule.forRoot([AppEffects])

269

]

270

})

271

export class AppModule {}

272

```

273

274

### Testing Support

275

276

Generated effects include comprehensive testing utilities.

277

278

```typescript

279

// Effect testing example

280

describe('UserEffects', () => {

281

let actions$: Observable<any>;

282

let effects: UserEffects;

283

let service: jasmine.SpyObj<UserService>;

284

285

beforeEach(() => {

286

TestBed.configureTestingModule({

287

providers: [

288

UserEffects,

289

provideMockActions(() => actions$),

290

{

291

provide: UserService,

292

useValue: jasmine.createSpyObj('UserService', ['getUsers'])

293

}

294

]

295

});

296

297

effects = TestBed.inject(UserEffects);

298

service = TestBed.inject(UserService) as jasmine.SpyObj<UserService>;

299

});

300

301

describe('loadUsers$', () => {

302

it('should return loadUsersSuccess on successful load', () => {

303

const users = [{ id: '1', name: 'John' }];

304

const action = UserActions.loadUsers();

305

const outcome = UserActions.loadUsersSuccess({ users });

306

307

actions$ = hot('-a', { a: action });

308

const response = cold('-a|', { a: users });

309

service.getUsers.and.returnValue(response);

310

311

const expected = cold('--b', { b: outcome });

312

expect(effects.loadUsers$).toBeObservable(expected);

313

});

314

});

315

});

316

```

317

318

### Performance Optimizations

319

320

Generated effects include performance best practices.

321

322

```typescript { .api }

323

/**

324

* Performance optimization patterns in effects

325

*/

326

interface PerformancePatterns {

327

/** Use switchMap for cancellable operations */

328

switchMap: 'switchMap(() => service.call())';

329

/** Use mergeMap for parallel operations */

330

mergeMap: 'mergeMap(() => service.call())';

331

/** Use concatMap for sequential operations */

332

concatMap: 'concatMap(() => service.call())';

333

/** Use exhaustMap to ignore new actions while processing */

334

exhaustMap: 'exhaustMap(() => service.call())';

335

}

336

```

337

338

```typescript

339

// Optimized effect patterns

340

@Injectable()

341

export class OptimizedEffects {

342

343

// Cancel previous requests when new search is triggered

344

searchUsers$ = createEffect(() =>

345

this.actions$.pipe(

346

ofType(UserActions.searchUsers),

347

debounceTime(300), // Debounce user input

348

distinctUntilChanged(

349

(prev, curr) => prev.query === curr.query

350

),

351

switchMap(({ query }) =>

352

this.userService.searchUsers(query).pipe(

353

map(users => UserActions.searchUsersSuccess({ users })),

354

catchError(error => of(UserActions.searchUsersFailure({ error })))

355

)

356

)

357

)

358

);

359

360

// Process operations in parallel

361

loadMultipleResources$ = createEffect(() =>

362

this.actions$.pipe(

363

ofType(AppActions.loadDashboard),

364

mergeMap(() => [

365

UserActions.loadUsers(),

366

ProductActions.loadProducts(),

367

OrderActions.loadOrders()

368

])

369

)

370

);

371

372

// Prevent multiple login attempts

373

login$ = createEffect(() =>

374

this.actions$.pipe(

375

ofType(AuthActions.login),

376

exhaustMap(({ credentials }) =>

377

this.authService.login(credentials).pipe(

378

map(user => AuthActions.loginSuccess({ user })),

379

catchError(error => of(AuthActions.loginFailure({ error })))

380

)

381

)

382

)

383

);

384

}

385

```

386

387

### WebSocket Effects

388

389

Effects for real-time communication with WebSocket integration.

390

391

```typescript

392

// WebSocket effect example

393

@Injectable()

394

export class WebSocketEffects {

395

396

connectToWebSocket$ = createEffect(() =>

397

this.actions$.pipe(

398

ofType(AppActions.initializeApp),

399

switchMap(() =>

400

this.webSocketService.connect().pipe(

401

map(message => WebSocketActions.messageReceived({ message })),

402

catchError(error => of(WebSocketActions.connectionError({ error })))

403

)

404

)

405

)

406

);

407

408

sendMessage$ = createEffect(() =>

409

this.actions$.pipe(

410

ofType(WebSocketActions.sendMessage),

411

tap(({ message }) => {

412

this.webSocketService.send(message);

413

})

414

),

415

{ dispatch: false }

416

);

417

418

constructor(

419

private actions$: Actions,

420

private webSocketService: WebSocketService

421

) {}

422

}

423

```