Jekyll Initial Commit

This commit is contained in:
David Erwin
2017-05-24 16:48:00 -04:00
parent a1a78334ea
commit 69b19d2c91
110 changed files with 13644 additions and 0 deletions
+223
View File
@@ -0,0 +1,223 @@
# Redux
Redux is a predictable state container for JavaScript apps.
To understand Redux we need to dive into a few concepts.
- [Actions](#actions)
- [Action Creators](#actions)
- [Action Types](#actions)
- [Reducers](#reducers)
- [Stores](#store)
## The three principles
These are the three principles to build Redux applications. The following are specified in the Redux Documentation [Three Principles · Redux](http://redux.js.org/docs/introduction/ThreePrinciples.html)
### Single source of truth
The state of your whole application is stored in an object tree within a single store. We are going to represent the whole state of our application in a single Javascript Object.
### State is read-only
The only way to change the state is to emit an action, an object describing what happened.
### Changes are made with pure functions
To specify how the state tree is transformed by actions, you write pure reducers.
## Actions
Actions describe that something happened in our application. They are payloads of information that send data to your store. __They are the only source of information for the store.__
Here is an example:
```js
const ADD_COMMENT = 'ADD_COMMENT';
{
type: ADD_COMMENT,
comment: 'This is my comment.'
}
```
Actions are JavaScript objects. Every action must have a `type` property that indicates the type of action being performed. Types should be defined as constants.
Once an app becomes big enough, you may want to move them into a separate module. We store them in a `contants.js` file. [auth.js Constants](https://github.com/coralproject/talk/blob/153193959cb4dfa5d8feaabb49811325f836ee68/client/coral-framework/constants/auth.js)
```js
import { ADD_COMMENT, REMOVE_COMMENT } from './constants'
```
We can dispatch an action by using `dispatch()`.
Our actions live within the `coral-framework/actions` folder. [talk/client/coral-framework/actions](https://github.com/coralproject/talk/tree/153193959cb4dfa5d8feaabb49811325f836ee68/client/coral-framework/actions)
More about Actions: [Actions · Redux](http://redux.js.org/docs/basics/Actions.html)
### Async Actions
For our async operations we dispatch three actions.
- `<ACTION_TYPE>_REQUEST`
- `<ACTION_TYPE>_SUCCESS`
- `<ACTION_TYPE>_FAILURE`
#### Request
We use the postfix `_REQUEST` to know that the resource is being requested.
#### Success
We use the postfix `_SUCCESS` to know that the resource response came back successfully.
#### Failure
We use the postfix `_FAILURE` to know that the resource request failed.
## Action Creators
Action Creators are functions that return actions. This makes it easier to use, portable and testable.
```js
function addComment(comment) {
return {
type: ADD_COMMENT,
comment
}
}
```
So we can later trigger those actions by using `dispatch()`
```js
dispatch(addComment(comment))
dispatch(removeComment(comment.id))
```
## Dispatch Function
The `dispatch()` function can be accessed directly from the store as `store.dispatch()`, but more likely you'll access it using a helper like react-redux's`connect()`.
We use `connect()`in our containers. More about this in Architecture.
## Reducers
With Actions we describe that something happened in our application. But we dont specify how our state will be modified with this change.
In a Reducer we will specify how the state of our application change when an action has been dispatched.
Here we also will want to specify the `initialState`
Before building reducers its important to that you:
- Dont mutate the state
- Return the previous state in the default case.
Here is an example of an auth reducer:
```js
const initialState = {
isLoading: false,
loggedIn: false,
user: null,
error: ''
};
function auth (state = initialState, action) {
switch (action.type) {
case actions.CHECK_LOGIN_REQUEST:
return Object.assign({}, state, {
isLoading: true
});
case actions.CHECK_LOGIN_SUCCESS:
return Object.assign({}, state, {
isLoading: false,
loggedIn: true,
user: action.user,
error: ''
});
case actions.CHECK_LOGIN_FAILURE:
return Object.assign({}, state, {
isLoading: false,
error: action.error,
loggedIn: false,
user: null
});
default:
return state
}
}
```
Notice that a reducer takes the `state` as first argument and when its not defined it returns the `initialState`. As a second argument it takes the `action`. We have our state and we have the action. This is the time to specify how we modify the state.
### Reducers using ImmutableJS
We are using ImmutableJS to maintain our app state. Here is a guide on how to use ImmutableJS.
This is how a simplified version of our [auth reducer](https://github.com/coralproject/talk/blob/153193959cb4dfa5d8feaabb49811325f836ee68/client/coral-framework/reducers/auth.js) looks like:
```js
const initialState = Map({
isLoading: false,
loggedIn: false,
user: null,
error: ‘’
});
function auth (state = initialState, action) {
switch (action.type) {
case CHECK_LOGIN_REQUEST:
return state
.set('isLoading', true);
case CHECK_LOGIN_SUCCESS:
return state
.set('isLoading', false)
.set('loggedIn', true)
.set('user', action.user)
.set('error', '');
});
case CHECK_LOGIN_FAILURE:
return state
.set('isLoading', false)
.set('error', action.error)
.set('loggedIn', false)
.set('user', null)
});
default:
return state
}
}
```
Looks cleaner, right?
Its pretty easy to follow. Here it says if a `CHECK_LOGIN_REQUEST` action has been dispatched set the `isLoading` from our state to `true`. And we can show a tiny loader to let the user now we are requesting something to the server.
Our actions live within the `coral-framework/reducers` folder. [talk/client/coral-framework/reducers ](https://github.com/coralproject/talk/tree/153193959cb4dfa5d8feaabb49811325f836ee68/client/coral-framework/reducers)
More about Reducers: [Reducers · Redux](http://redux.js.org/docs/basics/Reducers.html)
And the last thing we need to see is the __Store__
### Store
The `Store` is what holds the application state. Here we can access and update the state.
Its important to note that we will only have a single store in our application called `rootReducer` and we will use reducer composition instead of many stores.
Here is an example of how create a store with [createStore()](http://redux.js.org/docs/api/createStore.html) using a reducer:
```js
import { createStore } from 'redux'
import authReducer from './auth'
let store = createStore(authReducer)
```
We do have a lot of stores so we will need to combine all our reducers with [combineReducers()](http://redux.js.org/docs/api/combineReducers.html) within a single store
```js
import {combineReducers} from 'redux';
import authReducer from './auth'
import configReducer from './config'
import userReducer from './user'
const rootReducer = combineReducers({
authReducer,
configReducer,
userReducer
...
});
```
More about Stores: [Store · Redux](http://redux.js.org/docs/basics/Store.html)
## Useful Resources
[Redux Documentation · Redux](http://redux.js.org/)
[Getting Started with Redux](https://egghead.io/courses/getting-started-with-redux)
[Usage with React · Redux](http://redux.js.org/docs/basics/UsageWithReact.html)