Explorar o código

Merge branch 'master' of gitlab.com:bebeco/Tutorials

Tomi Cvetic %!s(int64=8) %!d(string=hai) anos
pai
achega
2b18006a0d
Modificáronse 1 ficheiros con 168 adicións e 55 borrados
  1. 168 55
      LearnRedux/Videos.md

+ 168 - 55
LearnRedux/Videos.md

@@ -1,3 +1,7 @@
+# Learn Redux
+* <https://learnredux.com/account>
+* <http://redux.js.org/docs/introduction/>
+
 ## Video 1: Setting up Webpack
 * React Dev Tools
 * Redux Dev Tools
@@ -6,28 +10,31 @@
 
 ## Video 3: Create Single and PhotoGrid components
 
-## Video 3: Setting up React Router
-```javascript
+## Video 4: Setting up React Router
+
+```jsx
 import { Router, Route, IndexRoute, browserHistory } from 'react-router'
 
 const router = (
     <Router history={browserHistory}>
         <Route path='/' component={Main}>
-            <IndexRoute component={} \/>
-            <Route path='/view/:postId' \/>
-        <\/Route>
-    <\/Router>
+            <IndexRoute component={} />
+            <Route path='/view/:postId' />
+        </Route>
+    </Router>
 )
 
 render(router, document.getElementById('root'))
 ```
+
 * Use `<Link to=''>Bla</Link>` to create push state links.
 * browserHistory will be replaced later by `history` which first syncs the browser history with the react store (see next video).
 
-## Video 4: Setting up React Store
+## Video 5: Setting up React Store
 * One giant state for all data
 * it is called `store`
-```javascript
+
+```jsx
 import { createStore, compose } from 'redux'
 import { syncHistoryWithStore } from 'react-router-redux'
 import { browserHistory } from 'react-router'
@@ -39,11 +46,12 @@ export const history = syncHistoryWithStore(browserHistory, store)
 export default store
 ```
 
-## Video 5: Redux Actions
+## Video 6: Redux Actions
 * actions invoke changes of the state (adding, updating, removing data)
 * actions are objects with two elements: type and payload
 * action creators are functions which return actions:
-```javascript
+
+```jsx
 function increment(index) {
     return {
         type: 'INCREMENT_LIKES',
@@ -60,7 +68,7 @@ function addComment(postId, author, comment) {
 }
 ```
 
-## Video 6: Redux Reducers
+## Video 7: Redux Reducers
 * reducers handle the data when an action is received
 * use one reducer per components
 * reducers are functions which take
@@ -68,7 +76,8 @@ function addComment(postId, author, comment) {
     - a copy of the current state
 * reducers return the updated state if there is a change, or the previous state
 * always start like this and then add some conditional functionality:
-```javascript
+
+```jsx
 function posts(state = [], action) {
     if (...) {
         return nextState
@@ -78,8 +87,10 @@ function posts(state = [], action) {
 
 export default posts
 ```
+
 * combine them in a root reducer
-```javascript
+
+```jsx
 import { combineReducers } from 'redux'
 import { routerReducer } from 'react-router-redux'
 
@@ -87,75 +98,177 @@ import posts from './posts'
 const rootReducer = combineReducers({ posts, ..., routing: routerReducer })
 export default rootReducer
 ```
+
 * always add `routing: routerReducer` at the end to integrate the route changes with other action changes.
 * executes URL changes implicitely
 * <https://github.com/reactjs/react-router-redux>
 
-## Video 7: Integrating our Store with React Router
+## Video 8: Integrating our Store with React Router
 * to make the store globally available, put it on top of the routing
 * replace the browserHistory as mentioned before.
-```diff
-import { Router, Route, IndexRoute, browserHistory } from 'react-router'
-+import { Provider } from 'react-redux'
-+import store, { history } from './store'
+    ```diff
+    import { Router, Route, IndexRoute, browserHistory } from 'react-router'
+    +import { Provider } from 'react-redux'
+    +import store, { history } from './store'
 
-const router = (
-+   <Provider store={store}>
--       <Router history={browserHistory}>
-+       <Router history={history}>
-            <Route path='/' component={Main}>
-                <IndexRoute component={} \/>
-                <Route path='/view/:postId' \/>
-            <\/Route>
-        <\/Router>
-+   </Provider>
-)
+    const router = (
+    +   <Provider store={store}>
+    -       <Router history={browserHistory}>
+    +       <Router history={history}>
+                <Route path='/' component={Main}>
+                    <IndexRoute component={} \/>
+                    <Route path='/view/:postId' \/>
+                <\/Route>
+            <\/Router>
+    +   </Provider>
+    )
 
-render(router, document.getElementById('root'))
-```
+    render(router, document.getElementById('root'))
+    ```
 * The state is now stored in the store. `$r.store.getState()` 
 
-## Video 8: Understanding the Reducer's Job and Dispatching Actions
+## Video 9: Understanding the Reducer's Job and Dispatching Actions
 * action creators return actions
 * actions invoke state changes
 * reducers change the state
 * the store provides a dispatch function
-```javascript
-// on the console
-$r.store.dispatch({type: 'INCREMENT', index: 1})
-```
+    
+    ```jsx
+    // on the console
+    $r.store.dispatch({type: 'INCREMENT', index: 1})
+    ```
 * The dispatcher sends the action to **every** reducer
 * Therefore, the reducer needs to have some conditional logic.
 
-## Video 9: Accessing dispatch and state with Redux
+## Video 10: Accessing dispatch and state with Redux
 * in regular React, the state or parts of it are propagated via props
 * in Redux, `connect` injects the data in the components that need it
 * for that, we wrap the main component with one that has the state and dispatcher propagated
-```javascript
-import { bindActionCreators } from 'redux'
-import { connect } from 'react-redux'
-import * as actionCreators from './actions/actionCreators'
-import Main from './Main'
+    
+    ```jsx
+    import { bindActionCreators } from 'redux'
+    import { connect } from 'react-redux'
+    import * as actionCreators from './actions/actionCreators'
+    import Main from './Main'
 
-function mapStateToProps(state) {
-    return {
-        posts: state.posts,
-        comments: state.comments,
+    function mapStateToProps(state) {
+        return {
+            posts: state.posts,
+            comments: state.comments,
+        }
     }
-}
 
-function mapDispatchToProps(dispatch) {
-    return bindActionCreators(actionCreators, dispatch)
-}
+    function mapDispatchToProps(dispatch) {
+        return bindActionCreators(actionCreators, dispatch)
+    }
 
-const App = connect(mapStateToProps, mapDispatchToProps)(Main)
-export default App
-```
+    const App = connect(mapStateToProps, mapDispatchToProps)(Main)
+    export default App
+    ```
 * because Main ist just JSX, connect injects standardized props into it and makes the state and dispatcher available.
 * You can still propagate data down with props
 
-## Video 10: Displaying Redux State inside our Components
+## Video 11: Displaying Redux State inside our Components
 * Creating React components
 
-## Video 11: Updating State with Reducers
+## Video 12: Updating State with Reducers
+* Once you propagate the reducer function to the component, this is how you pass arguments to the function call
+    - Remember that `<button onClick={this.props.function(argument)} ...>` would call the function at document load!
+    
+    ```html
+    <button onClick={this.props.function.bind(null, argument)} ...>
+    ```
+    
+* Use pure functions to manipulate state. So the same inputs (previous state, action) always gives the same output (next state).
+    - Makes testing easier.
+    - Enables Redux dev tools, time travel etc.
+* Do the same as in React state handling: Copy, modify, return copy:
+    
+    ```jsx
+    function posts(state = [], action) {
+        switch(action.type) {
+            const i = action.index
+            case 'INCREMENT_LIKES' :
+                return [
+                    ...state.slice(0, i),
+                    { ...state[i], likes: state[i].likes + 1 },
+                    ...state.slice(i + 1)
+                ]
+            default:
+                return state
+        }
+    }
+    ```
+
+## Video 13: Displaying the Single Photo Component
+* Polyfills are new ES6 functions cross compiled for old browsers through Babel. [Example for findIndex()]
+* You can use `findIndex()` to get a certain element of an array
+    
+    ```jsx
+    render () {
+        const { postId } = this.props.params
+        const i = this.props.posts.findIndex((post) => post.code === postId)
+        const post = this.props.posts[i]
+        const comments = this.props.comments[postId] || []
+        ...
+    }
+    ```
+[Example for findIndex()]: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex#Polyfill
+
+## Video 14: Displaying and Adding Comments
+* You can hide a submit button, if it's clear that the Return key submits the form.
+* consider separate render functions for looped-over elements to keep the functions clearer.
+
+## Video 15: Updating Comment State in our Store
+* Write a functions, which handles the submit of a form
+
+```jsx
+...
+handleSubmit(e) {
+    e.preventDefault()
+    const { postId } = this.props.params
+    const author = this.refs.author.value
+    this.props.addComment(postId, author, ...)
+}
+render() {
+    ...
+    <form ref='commentForm' className='comment-form' onSubmit={this.handleSubmit}>
+        <input type='text' ref='author' placeholder='author'/>
+    ...
+}
+```
+
+## Video 16: Redux Reducer Composition
+* Just like you can split up your state in different pieces, you can also split up the reducers. This is called reducer composition
+* Example for comments:
+    - write one function to handle all comments
+    - write other functions to only handle one comment at a time
+    
+    ```jsx
+    function postComments(state = [], action) {
+        switch (action.type) {
+            case 'ADD_COMMENT':
+                return [
+                    ...state, {
+                        user: action.author,
+                        text: action.comment,
+                    }
+                ]
+            default:
+                return state
+        }
+    }
+    function comments(state = [], action) {
+        if (typeof action.postId !== 'undefined') {
+            return {
+                ...state,
+                [action.postId]: postComments(state[action.postId], action)
+            }
+        }
+        return state
+    }
+
+    export default comment
+    ```
 
+## Video 18: Hot Reloading Redux Reducers with Webpack