What is one of the harder things, if not the hardest, you have ever done in an Angular project?
State
@devupconf - STL 2022
twitter.com/@nartc1410
github.com/nartc
and all the Sponsors (https://www.devupconf.org/sponsors)
and all the Sponsors (https://www.devupconf.org/sponsors)
When should we use state management?
– Any Angular developer ever
There should be 3 answers here
Never
Never
Never
Never
When needed or "it depends"
Never
Never
When needed or "it depends"
Always
Never
Never
When needed or "it depends"
Always
Never
Never
When needed or "it depends"
Always
Never
Never
When needed or "it depends"
Always
❌
Never
Never
When needed or "it depends"
Always
✅
and more.
(who doesn't like to own a State Management library)
Common?
Global State Management
What is State Management?
What is State Management?
FeatureA
FeatureB
FeatureC
StateA
StateB
StateC
App
FeatureA
FeatureB
FeatureC
StateA
StateB
StateC
App
FeatureA
FeatureB
FeatureC
StateA
StateB
StateC
App
FeatureA
FeatureB
FeatureC
StateA
StateB
StateC
App
Anything that contributes to rendering a component
Anything that contributes to rendering a component
Persisted State
Anything that contributes to rendering a component
Persisted State
URL State
Anything that contributes to rendering a component
Persisted State
URL State
Client State
Anything that contributes to rendering a component
Persisted State
URL State
Client State
Local UI State
Anything that contributes to rendering a component
Persisted State
URL State
Client State
Local UI State
Anything that contributes to rendering a component
Persisted State
URL State
Client State
Local UI State
What do we even want from a State Management solution?
In my opinion, a State Management solution should provide
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
- Ability to write to states fully or partially
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
- Ability to write to states fully or partially
- Ability to handle side-effects
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
- Ability to write to states fully or partially
- Ability to handle side-effects
- Ease of clean up
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
- Ability to write to states fully or partially
- Ability to handle side-effects
- Ease of clean up
@Injectable()
export class StateService {
private state$ = new ReplaySubject(1);
}
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
- Ability to write to states fully or partially
- Ability to handle side-effects
- Ease of clean up
@Injectable({ providedIn: 'root' })
export class StateService {
private state$ = new ReplaySubject(1);
}
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
- Ability to write to states fully or partially
- Ability to handle side-effects
- Ease of clean up
@Injectable()
export class StateService {
private state$ = new ReplaySubject(1);
}
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
- Ability to write to states fully or partially
- Ability to handle side-effects
- Ease of clean up
@Injectable()
export class StateService {
private state$ = new ReplaySubject(1);
select(selector) {
return this.state$.pipe(
map(state => selector(state)),
distinctUntilChanged()
)
}
}
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
- Ability to write to states fully or partially
- Ability to handle side-effects
- Ease of clean up
@Injectable()
export class StateService {
private state$ = new ReplaySubject(1);
select(selector) {
return this.state$.pipe(
map(state => selector(state)),
distinctUntilChanged()
)
}
setState(state) {
if (typeof state === 'function') {
this.state$.next(state(this.state$.getValue()));
} else {
this.state$.next(state);
}
}
patchState(partialState) {
const currentState = this.state$.getValue();
if (typeof partialState === 'function') {
this.state$.next({
...currentState,
...partialState(currentState)
});
} else {
this.state$.next({
...currentState,
...partialState
})
}
}
}
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
- Ability to write to states fully or partially
- Ability to handle side-effects
- Ease of clean up
@Injectable()
export class StateService {
private state$ = new ReplaySubject(1);
select(selector) {
return this.state$.pipe(
map(state => selector(state)),
distinctUntilChanged()
)
}
setState(state) {
// ...
}
patchState(partialState) {
// ...
}
effect(trigger) {
return trigger.subscribe();
}
}
In my opinion, a State Management solution should provide
- Ability to read states with some diffing mechanism
- Ability to write to states fully or partially
- Ability to handle side-effects
- Ease of clean up
@Injectable()
export class StateService {
private state$ = new ReplaySubject(1);
private destroy$ = new ReplaySubject(1);
select(selector) {
return this.state$.pipe(
map(state => selector(state)),
distinctUntilChanged()
)
}
setState(state) {
// ...
}
patchState(partialState) {
// ...
}
effect(trigger) {
return trigger
.pipe(takeUntil(this.destroy$))
.subscribe();
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}
@Injectable()
export class StateService {
private state$ = new ReplaySubject(1);
private destroy$ = new ReplaySubject(1);
select(selector) {
return this.state$.pipe(
map(state => selector(state)),
distinctUntilChanged()
)
}
setState(state) {
// ...
}
patchState(partialState) {
// ...
}
effect(trigger) {
return trigger
.pipe(takeUntil(this.destroy$))
.subscribe();
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}
Congratulations!
You just implemented
@ngrx/component-store
Read
Write
Side-effect
Read
Write
Side-effect
@ngrx/store
Read
Write
Side-effect
@ngrx/store
createSelector()
createReducer()
createEffect()
Read
Write
Side-effect
@ngrx/store
createSelector()
createReducer()
createEffect()
@ngrx/component-store
select()
setState()
effect()
Demo
Credits
Laura - https://twitter.com/ltciro
Diana - https://twitter.com/dicaro87