Basic Tutorial Flashcards
What are actions?
Actions are plain JavaScript objects or payloads of information that send data from your application to your store.
What is the only source of information for the store?
Actions.
How do you send an action to the store?
By using using store.dispatch().
What must actions have?
A type property that indicates the type of action being performed.
What should types typically be defined as?
String constants.
What is this an example of?
const ADD_TODO = ‘ADD_TODO’
{
type: ADD_TODO,
text: ‘Build my first Redux app’
}
An action which represents adding a new todo item.
What might you want to do once your app is large enough?
Move Actions into a separate module.
It’s a good idea to pass as little data in each action as possible.
For example, it’s better to pass index than the whole todo object.
What are action creators?
Functions that create actions.
Why would you use an action creator to return an action?
To make them portable and easy to test.
What is an example of an action creator?
function addTodo(text) { return { type: ADD_TODO, text } }
How would you initiate a dispatch in Redux?
Pass the result to the dispatch() function, or create a bound action creator that automatically dispatches.
Give a simple example of passing a result to a dispatch() function.
dispatch(addTodo(text))
dispatch(completeTodo(index))
Give a simple example of how you would create a bound action creator that automatically dispatches.
const boundAddTodo = text => dispatch(addTodo(text)) const boundCompleteTodo = index => dispatch(completeTodo(index))
What is the advantage of using a bound action creator that automatically dispatches?
You can call them directly.
Give a simple example of how you would directly call a bound action creator that automatically dispatches.
boundAddTodo(text)
boundCompleteTodo(index)
How would you directly access the the dispatch() function from the store?
by using store.dispatch() or more likely by accessing it using a helper like react-redux’s connect().
How would you automatically bind many action creators to a dispatch() function?
By using bindActionCreators()
What do reducers do?
They specify how the application’s state changes in response to actions sent to the store.
How do actions differ from reducers?
Actions only describe what happened, but don’t describe how the application’s state changes.
How is all the applications state stored?
In a single object.
What is a good practice before creating an apps state?
To figure out the minimal representation of your app’s state as an object.
what should you do if you need to store some data, as well as some UI state, in the state tree?
Try to keep them separate.
What’s a best practice when creating an apps state?
To keep it as normalized as possible, without any nesting and to keep every entity in an object stored with an ID as a key, and use IDs to reference it from other entities, or lists.
What is a reducer?
A pure function that takes the previous state and an action, and returns the next state.
Give an example of a reducer.
(previousState, action) => nextState
Why is it called a reducer?
Because it’s the type of function you would pass to Array.prototype.reduce(reducer, ?initialValue).
What should you never do in a reducer?
Mutate its arguments
Perform side effects like API calls and routing transitions
Call non-pure functions, e.g. Date.now() or Math.random()
What should a reducer do?
Given the same arguments, it should calculate the next state and return it. No surprises. No side effects. No API calls. No mutations. Just a calculation.
What will Redux do the first time?
Call our reducer with an undefined state
When Redux calls our reducer for the first time, what is this a good opportunity to do?
To return the initial state of our app.
Convert this code to take advantage of ES6
default argument syntax:
import { VisibilityFilters } from './actions' const initialState = { visibilityFilter: VisibilityFilters.SHOW_ALL, todos: [] } function todoApp(state, action) { if (typeof state === 'undefined') { return initialState } // For now, don't handle any actions // and just return the state given to us. return state }
import { VisibilityFilters } from './actions' const initialState = { visibilityFilter: VisibilityFilters.SHOW_ALL, todos: [] } function todoApp(state = initialState, action) { // For now, don't handle any actions // and just return the state given to us. return state }
What do you notice with this code?
import { SET_VISIBILITY_FILTER, VisibilityFilters } from './actions' ... function todoApp(state = initialState, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return Object.assign({}, state, { visibilityFilter: action.filter }) default: return state } }
We don’t mutate the state. We create a copy with Object.assign().
NOTE:
Object.assign(state, { visibilityFilter: action.filter }) is also wrong: it will mutate the first argument. You must supply an empty object as the first parameter.
We return the previous state in the default case. It’s important to return the previous state for any unknown action.
What is noteworthy about Object.assign?
It’s part of ES6, and is not supported by older browsers. To support them, you will need to either use a polyfill, a Babel plugin, or a helper from another library like _.assign().
How would you update a specific item in an array without resorting to mutations?
Create a new array with the same items except the item at the index.
If you find yourself often wanting to update a specific item in an array without resorting to mutations, what is it a good idea to do?
Use a helper like immutability-helper, updeep, or even a library like Immutable that has native support for deep updates.
When is the only time you can assign to anything inside the state?
When you clone it first.
What do you notice here?
function todos(state = [], action) { switch (action.type) { case ADD_TODO: return [ ...state, { text: action.text, completed: false } ] case TOGGLE_TODO: return state.map((todo, index) => { if (index === action.index) { return Object.assign({}, todo, { completed: !todo.completed }) } return todo }) default: return state } } function todoApp(state = initialState, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return Object.assign({}, state, { visibilityFilter: action.filter }) case ADD_TODO: return Object.assign({}, state, { todos: todos(state.todos, action) }) case TOGGLE_TODO: return Object.assign({}, state, { todos: todos(state.todos, action) }) default: return state } }
todos also accepts state—but state is an array! Now todoApp gives todos just a slice of the state to manage, and todos knows how to update just that slice. This is called reducer composition, and it’s the fundamental pattern of building Redux apps.
reducer1
qw
reducer2
qw
reducer3
sd
reducer4
reducer5
11