Redux Flashcards

1
Q

Redux uses pure functions heavily

A

Pure functions return a new value based on arguments passed to them. They don’t modify existing objects; instead, they return a new one. These functions don’t rely on the state they’re called from, and they return only one and the same result for any provided argument.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Redux has three building parts

A

actions, store and reducers

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

actions are events

A

{ type: LOGIN_FORM_SUBMIT, payload: {username: ‘alex’, password: ‘123456’} }

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Actions are created with action creators, which are just

A

functions that return actions function authUser(form) { return { type: LOGIN_FORM_SUBMIT, payload: form } }

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Calling actions anywhere in the app, then, is very easy. Use the

A

dispatch method, like so: dispatch(authUser(form));

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

reducers have a somewhat different meaning from functional Javascript (where they take multiple values and consolidate to one, or act upon streams). In Redux . . .

A

reducers are functions (pure) that take the current state of the application and an action and then return a new state

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Here is a very simple reducer that takes the current state and an action as arguments and then returns the next state

A

function handleAuth(state, action) { return _.assign({}, state, { auth: action.payload }); }

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

For more complex apps, it is recommended to use the

A

combineReducers() utility provided by Redux

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

If an object (state) changes only some values, Redux creates a

A

new object, the values that didn’t change will refer to the old object and only new values will be created. That’s great for performance

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

const rootReducer (example)

A

const rootReducer = combineReducers({ handleAuth: handleAuth, editProfile: editProfile, changePassword: changePassword });

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Store is the object that holds the application state and provides a few helper methods to

A

access the state, dispatch actions and register listeners. The entire state is represented by a single store

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Any action returns a

A

new state via reducers. That makes Redux very simple and predictable.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

(simple example of a store)

A

import { createStore } from ‘redux’; let store = createStore(rootReducer); let authInfo = {username: ‘alex’, password: ‘123456’}; store.dispatch(authUser(authInfo));

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Redux has a slightly different implementation of time travel than Flux. In Redux, you can

A

go back to a previous state and even take your state in a different direction from that point on

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Redux DevTools supports the following “time travel” features in the Redux workflow (think of them as Git commands for your state):

A

Reset: resets to the state your store was created with Revert: goes back to the last committed state Sweep: removes all disabled actions that you might have fired by mistake Commit: makes the current state the initial state

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

The time-travel feature is not

A

efficient in production and is only intended for development and debugging. The same goes for DevTools

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Redux makes testing much easier because

A

it uses functional JavaScript as a base, and small independent functions are easy to test. So, if you need to change something in your state tree, import only one reducer that is responsible for that state, and test it in isolation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

How to make the state available to components

A

A best practice is to push the state down to children components

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

To make everything work together, we have to register the store listener with a

A

subscribe helper method

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

ngrx/store

A

Store builds on the concepts made popular by Redux, a popular state management container in the React community, and supercharges it with the backing of RxJS.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

your store can be thought of as a

A

client side ‘single source of truth’, or database. By adhering to the 1 store contract when designing your application, a snapshot of store at any point will supply a complete representation of relevant application state

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

reducer interface

A

export interface Reducer { (state: T, action: Action): T; }

23
Q

reducer (sample)

A

export const counter: Reducer = (state: number = 0, action: Action) => { switch(action.type){ case ‘INCREMENT’: return state + 1; case ‘DECREMENT’: return state - 1; default: return state; } };

24
Q

action interface

A

export interface Action { type: string; payload?: any; }

25
Q

how do we extract, combine, and project data from store for display in our views?

A

Because store itself is an observable, we have access to the typical JS collection operations you are accustom to (map, filter, reduce, etc.) along with a wide-array of extremely powerful RxJS based observable operators. This makes slicing up store data into any projection you wish quite easy

26
Q

projecting state data (sample)

A

//most basic example, get people from state store.select(‘people’) //combine multiple state slices Observable.combineLatest( store.select(‘people’), store.select(‘events’), (people, events) => { //projection here })

27
Q

A component invoking an action (sample)

A

increment(){ this.store.dispatch({type: ‘INCREMENT’}); }

28
Q

Because store provides an entry point both before and after dispatched actions hit application reducers

A

problems such as syncing slices of state to local storage, advanced logging, and implementing sagas are easily solved with a quick package include and a few lines of code

29
Q

All state updates are handled in reducers, which are pure functions

A

Pure functions are extremely simple to test, as it is simply input in, assert against output. This enables the testing of the most crucial aspects of your application without mocks, spies, or other tricks that can make testing both complex and error prone

30
Q

The two pillars of @ngrx/store, the store and dispatcher, both extend

A

RxJS Subjects

31
Q

Subjects are both Observables and Observers, meaning

A

you can subscribe to a Subject, but can also subscribe a Subject to a source. At a high-level Subjects can be thought of as messengers, or proxies; because Subjects are Observers, you can ‘next’, or pass values into the stream directly

32
Q

the Dispatcher extends Subject, adding

A

a dispatch method as a passthrough to the classic next method

33
Q

While vanilla Subjects work perfectly as a ‘dispatcher’, they have one issue that prevents them from being a good fit for store

A

When subscribing to a Subject, only values emitted after the subscription are received. This is unacceptable in an environment where components will be consistently added and removed, requiring the latest, on-demand sections of state from the application store at the time of subscription

34
Q

RxJS offers a convienant extension of Subject to handle this problem, the BehaviorSubject. BehaviorSubjects encapsulate all of the functionality of Subject, but also

A

return the last emitted value to subscribers upon subscription. This means components and services will always have access to the latest (or initial) application state and all future updates

35
Q

In a Store application, all dispatched actions must be passed through a specific pipeline before a new representation of state is passed into store, to be emitted to all observers. You can think of this as a factory assembly line, in this case the stations on the line are

A

pre-middleware -> reducers -> post-middleware -> store

36
Q

Reducers are the foundation of any Store or Redux-based application, describing sections of state and their potential transformations based on dispatched action types

A

Like a snowball rolling down hill, reducers accumulate value through iteration…

37
Q

Inspired by Redux, @ngrx/store has the concept of

A

Reducer functions used to manipulate specific slices of state. Reducers accept a state and action parameter, exposing a switch statement (generally, although this could be handled multiple ways) defining action types in which the reducer is concerned

38
Q

Each time an action is dispatched, each reducer registered to store will be called through . . .

A

the root reducer (created during provideStore at application bootstrap), passed the current state for that state slice (accumulator) and the dispatched action

39
Q

Scan behaves in a similar fashion to reduce, except

A

the accumulator value is maintained over time, or until the observable with scan applied has completed. For instance, as actions are dispatched and new state output, the accumulator in the scan function will always be the last output representation of state

40
Q

the store’s “select” method

A

select(key : string) { return this .map(state => state[key]) .distinctUntilChanged(); }

41
Q

the store’s “select” method

A

select(key : string) { return this .map(state => state[key]) .distinctUntilChanged(); }

42
Q

role of store vs reducers

A

As the application store maintains state, reducers are the workhorse behind the manipulation and output of new state representations as actions are dispatched. Each reducer should be focused on a specific section, or slice of state, similar to a table in a database

43
Q

chief idiom when working on reducers

A

never mutate previous state and always return a new representation of state when a relevant action is dispatched. Instead of using mutative methods like push, or reassigning values to previously existing objects, you will instead lean on none mutating methods like concat and Object.assign to return new values

44
Q

People reducer (sample)

A

const personDetails = (state, action) => { switch(action.type){ case ADD_GUEST: if(state.id === action.payload){ return Object.assign({}, state, {guests: state.guests + 1}); } return state;

45
Q

action constants

A

//Person Action Constants export const ADD_PERSON = ‘ADD_PERSON’; export const REMOVE_PERSON = ‘REMOVE_PERSON’;

46
Q

smart components

A

Smart, or Container components should be your root level, routable components. These components generally have direct access to store or a derivative. Smart components handle view events and the dispatching of actions, whether through a service or directly. Smart components also handle the logic behind events emitted up from child components within the same view.

47
Q

dumb components

A

dumb, or Child components are generally for presentation only, relying exclusively on @Input parameters, acting on the receieved data in an appropriate manner. When relevant events occur in dumb components, they are emitted up to be handled by a parent smart component. Dumb components will make up the majority of your application, as they should be small, focused, and reusable.

48
Q

when do you need to unsubscribe to a store?

A

/* if you do not use async pipe and create manual subscriptions always remember to unsubscribe in ngOnDestroy */ ngOnDestroy(){ this.subscription.unsubscribe(); }

49
Q

sample of a dumb component

A

export class PersonList { /* “dumb” components do nothing but display data based on input and emit relevant events back up for parent, or “container” components to handle */ @Input() people; @Output() addGuest = new EventEmitter(); @Output() removeGuest = new EventEmitter(); @Output() removePerson = new EventEmitter(); @Output() toggleAttending = new EventEmitter(); }

50
Q

AsyncPipe is

A

a unique, stateful pipe in Angular 2 meant for handling both Observables and Promises. When using the AsyncPipe in a template expression with Observables, the supplied Observable is subscribed to, with emitted values being displayed within your view. This pipe also handles unsubscribing to the supplied observable, saving you the mental overhead of manually cleaning up subscriptions in ngOnDestroy. In a Store application, you will find yourself leaning on the AsyncPipe heavily in nearly all of your component views

51
Q

using AsyncPipe

A

You can pipe any Observable (or promise) through async and a subscription will be created, updating the template value on source emission

52
Q

Redux (visual)

A
53
Q

Redux in motion

A
54
Q

The concept behind onPush

A

The concept behind OnPush is straightforward, when components rely solely on inputs, and those input references do not change, Angular can skip running change detection on that section of the component tree. As discussed previously, all delegating of state should be handled in smart, or top level components. This leaves the majority of components in our application relying solely on input, safely allowing us to set the ChangeDetectionStrategy to OnPush in the component definition. These components can now forgo change detection until necessary