├── .gitignore ├── 001 - Combining Redux and Firebase ├── .babelrc ├── README.md ├── index.html ├── package.json ├── src │ ├── actions │ │ ├── index.js │ │ └── types.js │ ├── components │ │ ├── app.js │ │ └── post_item.js │ ├── index.js │ └── reducers │ │ ├── index.js │ │ └── posts_reducer.js ├── style │ └── style.css ├── test │ ├── components │ │ └── app_test.js │ └── test_helper.js └── webpack.config.js ├── 002 - Basics of Redux Thunk ├── .babelrc ├── .gitignore ├── README.md ├── index.html ├── package.json ├── src │ ├── actions │ │ └── index.js │ ├── components │ │ └── app.js │ ├── index.js │ └── reducers │ │ └── index.js ├── style │ └── style.css ├── test │ ├── components │ │ └── app_test.js │ └── test_helper.js └── webpack.config.js ├── 003 - Dynamic Forms with Redux Form ├── .babelrc ├── .gitignore ├── README.md ├── index.html ├── package.json ├── src │ ├── actions │ │ └── index.js │ ├── components │ │ ├── app.js │ │ ├── posts_index.js │ │ ├── posts_new.bak.js │ │ ├── posts_new.js │ │ └── posts_show.js │ ├── index.js │ ├── reducers │ │ ├── index.js │ │ └── reducer_posts.js │ └── routes.js ├── style │ └── style.css └── webpack.config.js ├── 004 - Logicless Components with Reselect ├── .babelrc ├── .gitignore ├── README.md ├── index.html ├── package.json ├── src │ ├── actions │ │ ├── index.js │ │ └── types.js │ ├── components │ │ ├── app.js │ │ ├── posts_list.js │ │ └── selected_posts_list.js │ ├── index.js │ ├── reducers │ │ ├── index.js │ │ ├── reducer_posts.js │ │ └── reducer_selected_posts.js │ └── selectors │ │ └── selected_posts.js ├── style │ └── style.css └── webpack.config.js ├── 005 - A Better Way to Load Data ├── .babelrc ├── README.md ├── index.html ├── package.json ├── src │ ├── actions │ │ ├── index.js │ │ └── types.js │ ├── components │ │ ├── app.js │ │ └── photos.js │ ├── index.js │ ├── reducers │ │ ├── index.js │ │ └── photos_reducer.js │ ├── routes │ │ ├── index.js │ │ └── route_callbacks.js │ └── store.js ├── style │ └── style.css ├── test │ ├── components │ │ └── app_test.js │ └── test_helper.js └── webpack.config.js ├── 006 - Animation of React Components ├── .babelrc ├── README.md ├── index.html ├── npm-debug.log ├── package.json ├── src │ ├── actions │ │ └── index.js │ ├── components │ │ └── app.js │ ├── index.js │ └── reducers │ │ └── index.js ├── style │ └── style.css ├── test │ ├── components │ │ └── app_test.js │ └── test_helper.js └── webpack.config.js ├── 008 - Building Modals with React ├── .babelrc ├── .gitignore ├── README.md ├── index.html ├── package.json ├── src │ ├── actions │ │ └── index.js │ ├── components │ │ ├── app.js │ │ ├── bad_modal.js │ │ ├── colors.js │ │ └── modal.js │ ├── index.js │ └── reducers │ │ └── index.js ├── style │ └── style.css ├── test │ ├── components │ │ └── app_test.js │ └── test_helper.js └── webpack.config.js ├── 011 ├── .babelrc ├── .gitignore ├── README.md ├── index.html ├── package.json ├── server.js ├── src │ ├── actions │ │ └── index.js │ ├── components │ │ ├── app.js │ │ └── child.js │ ├── index.js │ └── reducers │ │ └── index.js ├── style │ └── style.css ├── test │ ├── components │ │ └── app_test.js │ └── test_helper.js └── webpack.config.js ├── 013 - Deployment of Webpack Apps ├── .babelrc ├── .gitignore ├── index.html ├── package.json ├── server.js ├── src │ ├── components │ │ ├── search_bar.js │ │ ├── video_detail.js │ │ ├── video_item.js │ │ └── video_list.js │ └── index.js ├── style │ └── style.css └── webpack.config.js ├── 016 ├── .babelrc ├── .gitignore ├── README.md ├── index.html ├── package.json ├── src │ ├── actions │ │ └── index.js │ ├── components │ │ ├── app.js │ │ └── google_map.js │ ├── index.js │ └── reducers │ │ └── index.js ├── style │ └── style.css ├── test │ ├── components │ │ └── app_test.js │ └── test_helper.js └── webpack.config.js ├── 017 - React Native Testing ├── rn_cli_example │ ├── .babelrc │ ├── .buckconfig │ ├── .flowconfig │ ├── .gitattributes │ ├── .gitignore │ ├── .watchmanconfig │ ├── __tests__ │ │ ├── index.android.js │ │ └── index.ios.js │ ├── android │ │ ├── app │ │ │ ├── BUCK │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src │ │ │ │ └── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── rn_cli_example │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ │ └── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ ├── keystores │ │ │ ├── BUCK │ │ │ └── debug.keystore.properties │ │ └── settings.gradle │ ├── app.json │ ├── index.android.js │ ├── index.ios.js │ ├── ios │ │ ├── rn_cli_example-tvOS │ │ │ └── Info.plist │ │ ├── rn_cli_example-tvOSTests │ │ │ └── Info.plist │ │ ├── rn_cli_example.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ ├── rn_cli_example-tvOS.xcscheme │ │ │ │ └── rn_cli_example.xcscheme │ │ ├── rn_cli_example │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.m │ │ │ ├── Base.lproj │ │ │ │ └── LaunchScreen.xib │ │ │ ├── Images.xcassets │ │ │ │ └── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ └── main.m │ │ └── rn_cli_exampleTests │ │ │ ├── Info.plist │ │ │ └── rn_cli_exampleTests.m │ ├── package.json │ └── yarn.lock └── testing │ ├── .babelrc │ ├── .flowconfig │ ├── .gitignore │ ├── .watchmanconfig │ ├── App.js │ ├── App.test.js │ ├── README.md │ ├── __snapshots__ │ └── App.test.js.snap │ ├── app.json │ ├── package.json │ └── yarn.lock ├── 018 - RN vs Flutter ├── .gitkeep └── diagrams.xml ├── 019 - Animations ├── .gitkeep ├── dev │ ├── .gitignore │ ├── .idea │ │ ├── libraries │ │ │ ├── Dart_SDK.xml │ │ │ └── Flutter_for_Android.xml │ │ ├── modules.xml │ │ ├── runConfigurations │ │ │ └── main_dart.xml │ │ └── workspace.xml │ ├── .metadata │ ├── README.md │ ├── android │ │ ├── .gitignore │ │ ├── app │ │ │ ├── build.gradle │ │ │ └── src │ │ │ │ └── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── scoped │ │ │ │ │ └── MainActivity.java │ │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── ios │ │ ├── .gitignore │ │ ├── Flutter │ │ │ ├── AppFrameworkInfo.plist │ │ │ ├── Debug.xcconfig │ │ │ └── Release.xcconfig │ │ ├── Runner.xcodeproj │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace │ │ │ │ └── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ ├── Runner.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── Runner │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.m │ │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ └── LaunchImage.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ └── README.md │ │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ │ ├── Info.plist │ │ │ └── main.m │ ├── lib │ │ └── main.dart │ ├── pubspec.lock │ ├── pubspec.yaml │ ├── scoped.iml │ ├── scoped_android.iml │ └── test │ │ └── widget_test.dart ├── diagrams.xml └── prod │ ├── .gitignore │ ├── .idea │ ├── libraries │ │ ├── Dart_SDK.xml │ │ └── Flutter_for_Android.xml │ ├── modules.xml │ ├── runConfigurations │ │ └── main_dart.xml │ └── workspace.xml │ ├── .metadata │ ├── README.md │ ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── prod │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle │ ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ └── contents.xcworkspacedata │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── main.m │ ├── lib │ └── main.dart │ ├── prod.iml │ ├── prod_android.iml │ ├── pubspec.lock │ ├── pubspec.yaml │ └── test │ └── widget_test.dart ├── 20 - redux ├── .gitkeep ├── code.js └── diagrams.xml ├── LICENSE.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"] 3 | } 4 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/README.md: -------------------------------------------------------------------------------- 1 | # ReduxSimpleStarter 2 | 3 | Interested in learning [Redux](https://www.udemy.com/react-redux/)? 4 | 5 | ###Getting Started### 6 | 7 | There are two methods for getting started with this repo. 8 | 9 | ####Familiar with Git?##### 10 | Checkout this repo, install depdencies, then start the gulp process with the following: 11 | 12 | ``` 13 | > git clone git@github.com:StephenGrider/ReduxSimpleStarter.git 14 | > cd ReduxSimpleStarter 15 | > npm install 16 | > npm start 17 | ``` 18 | 19 | ####Not Familiar with Git?##### 20 | Click [here](https://github.com/StephenGrider/ReactStarter/releases) then download the .zip file. Extract the contents of the zip file, then open your terminal, change to the project directory, and: 21 | 22 | ``` 23 | > npm install 24 | > npm start 25 | ``` 26 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redux-simple-starter", 3 | "version": "1.0.0", 4 | "description": "Simple starter package for Redux with React and Babel support", 5 | "main": "index.js", 6 | "repository": "git@github.com:StephenGrider/ReduxSimpleStarter.git", 7 | "scripts": { 8 | "start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js", 9 | "test": "mocha --compilers js:babel-core/register --require ./test/test_helper.js --recursive ./test", 10 | "test:watch": "npm run test -- --watch" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "babel-core": "^6.2.1", 16 | "babel-loader": "^6.2.0", 17 | "babel-preset-es2015": "^6.1.18", 18 | "babel-preset-react": "^6.1.18", 19 | "chai": "^3.5.0", 20 | "chai-jquery": "^2.0.0", 21 | "jquery": "^2.2.1", 22 | "jsdom": "^8.1.0", 23 | "mocha": "^2.4.5", 24 | "react-addons-test-utils": "^0.14.7", 25 | "webpack": "^1.12.9", 26 | "webpack-dev-server": "^1.14.0" 27 | }, 28 | "dependencies": { 29 | "babel-preset-stage-1": "^6.1.18", 30 | "firebase": "^2.4.2", 31 | "lodash": "^3.10.1", 32 | "react": "^0.14.3", 33 | "react-dom": "^0.14.3", 34 | "react-redux": "^4.0.0", 35 | "react-router": "^2.0.1", 36 | "redux": "^3.0.4", 37 | "redux-thunk": "^2.0.1" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/src/actions/index.js: -------------------------------------------------------------------------------- 1 | import Firebase from 'firebase'; 2 | import _ from 'lodash'; 3 | import { 4 | FETCH_POSTS, 5 | DELETE_POST, 6 | CREATE_POST 7 | } from './types'; 8 | 9 | const Posts = new Firebase('https://fbredux.firebaseio.com/'); 10 | 11 | export function fetchPosts() { 12 | return dispatch => { 13 | Posts.on('value', snapshot => { 14 | dispatch({ 15 | type: FETCH_POSTS, 16 | payload: snapshot.val() 17 | }); 18 | }); 19 | }; 20 | } 21 | 22 | export function createPost(post) { 23 | return dispatch => Posts.push(post); 24 | } 25 | 26 | export function deletePost(key) { 27 | return dispatch => Posts.child(key).remove(); 28 | } 29 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/src/actions/types.js: -------------------------------------------------------------------------------- 1 | export const FETCH_POSTS = 'FETCH_POSTS'; 2 | export const UPDATE_POST = 'UPDATE_POST'; 3 | export const DELETE_POST = 'DELETE_POST'; 4 | export const CREATE_POST = 'CREATE_POST'; 5 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/src/components/app.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import React, { Component } from 'react'; 3 | import { connect } from 'react-redux'; 4 | import * as actions from '../actions'; 5 | import PostItem from './post_item'; 6 | 7 | class App extends Component { 8 | state = { post: '' }; 9 | 10 | componentWillMount() { 11 | this.props.fetchPosts(); 12 | } 13 | 14 | handleInputChange(event) { 15 | this.setState({ post: event.target.value }); 16 | } 17 | 18 | handleFormSubmit(event) { 19 | event.preventDefault(); 20 | 21 | this.props.createPost(this.state.post) 22 | } 23 | 24 | renderPosts() { 25 | return _.map(this.props.posts, (post, key) => { 26 | return 27 | }); 28 | } 29 | 30 | render() { 31 | return ( 32 |
33 |

Create a Post

34 |
35 |
36 | 41 | 42 |
43 |
44 | 47 |
48 | ); 49 | } 50 | } 51 | 52 | function mapStateToProps(state) { 53 | return { posts: state.posts }; 54 | } 55 | 56 | export default connect(mapStateToProps, actions)(App) 57 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/src/components/post_item.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import * as actions from '../actions'; 4 | 5 | class PostItem extends Component { 6 | handleClick() { 7 | this.props.deletePost(this.props.id); 8 | } 9 | 10 | render() { 11 | return ( 12 |
  • 13 | {this.props.post} 14 | 19 |
  • 20 | ); 21 | } 22 | } 23 | 24 | export default connect(null, actions)(PostItem); 25 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { createStore, applyMiddleware } from 'redux'; 5 | import reduxThunk from 'redux-thunk'; 6 | 7 | import App from './components/app'; 8 | import reducers from './reducers'; 9 | 10 | const createStoreWithMiddleware = applyMiddleware(reduxThunk)(createStore); 11 | 12 | ReactDOM.render( 13 | 14 | 15 | 16 | , document.querySelector('.container')); 17 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import postsReducer from './posts_reducer'; 3 | 4 | const rootReducer = combineReducers({ 5 | posts: postsReducer 6 | }); 7 | 8 | export default rootReducer; 9 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/src/reducers/posts_reducer.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import { 3 | FETCH_POSTS, 4 | CREATE_POST, 5 | DELETE_POST 6 | } from '../actions/types'; 7 | 8 | export default function(state = {}, action) { 9 | switch (action.type) { 10 | case FETCH_POSTS: 11 | return action.payload; 12 | case CREATE_POST: 13 | return { ...state, ...action.payload }; 14 | case DELETE_POST: 15 | return _.omit(state, action.payload); 16 | } 17 | 18 | return state; 19 | } 20 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/style/style.css: -------------------------------------------------------------------------------- 1 | li.list-group-item { 2 | display: flex; 3 | justify-content: space-between; 4 | align-items: center; 5 | } 6 | 7 | form { 8 | margin: 10px 0px; 9 | } 10 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/test/components/app_test.js: -------------------------------------------------------------------------------- 1 | import { renderComponent , expect } from '../test_helper'; 2 | import App from '../../src/components/app'; 3 | 4 | describe('App' , () => { 5 | let component; 6 | 7 | beforeEach(() => { 8 | component = renderComponent(App); 9 | }); 10 | 11 | it('renders something', () => { 12 | expect(component).to.exist; 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/test/test_helper.js: -------------------------------------------------------------------------------- 1 | import _$ from 'jquery'; 2 | import React from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | import TestUtils from 'react-addons-test-utils'; 5 | import jsdom from 'jsdom'; 6 | import chai, { expect } from 'chai'; 7 | import chaiJquery from 'chai-jquery'; 8 | import { Provider } from 'react-redux'; 9 | import { createStore } from 'redux'; 10 | import reducers from '../src/reducers'; 11 | 12 | global.document = jsdom.jsdom(''); 13 | global.window = global.document.defaultView; 14 | const $ = _$(window); 15 | 16 | chaiJquery(chai, chai.util, $); 17 | 18 | function renderComponent(ComponentClass, props = {}, state = {}) { 19 | const componentInstance = TestUtils.renderIntoDocument( 20 | 21 | 22 | 23 | ); 24 | 25 | return $(ReactDOM.findDOMNode(componentInstance)); 26 | } 27 | 28 | $.fn.simulate = function(eventName, value) { 29 | if (value) { 30 | this.val(value); 31 | } 32 | TestUtils.Simulate[eventName](this[0]); 33 | }; 34 | 35 | export {renderComponent, expect}; 36 | -------------------------------------------------------------------------------- /001 - Combining Redux and Firebase/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: [ 3 | './src/index.js' 4 | ], 5 | output: { 6 | path: __dirname, 7 | publicPath: '/', 8 | filename: 'bundle.js' 9 | }, 10 | module: { 11 | loaders: [{ 12 | exclude: /node_modules/, 13 | loader: 'babel' 14 | }] 15 | }, 16 | resolve: { 17 | extensions: ['', '.js', '.jsx'] 18 | }, 19 | devServer: { 20 | historyApiFallback: true, 21 | contentBase: './' 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"] 3 | } 4 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | bundle.js 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/README.md: -------------------------------------------------------------------------------- 1 | # ReduxSimpleStarter 2 | 3 | Interested in learning [Redux](https://www.udemy.com/react-redux/)? 4 | 5 | ###Getting Started### 6 | 7 | There are two methods for getting started with this repo. 8 | 9 | ####Familiar with Git?##### 10 | Checkout this repo, install depdencies, then start the gulp process with the following: 11 | 12 | ``` 13 | > git clone git@github.com:StephenGrider/ReduxSimpleStarter.git 14 | > cd ReduxSimpleStarter 15 | > npm install 16 | > npm start 17 | ``` 18 | 19 | ####Not Familiar with Git?##### 20 | Click [here](https://github.com/StephenGrider/ReactStarter/releases) then download the .zip file. Extract the contents of the zip file, then open your terminal, change to the project directory, and: 21 | 22 | ``` 23 | > npm install 24 | > npm start 25 | ``` 26 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redux-simple-starter", 3 | "version": "1.0.0", 4 | "description": "Simple starter package for Redux with React and Babel support", 5 | "main": "index.js", 6 | "repository": "git@github.com:StephenGrider/ReduxSimpleStarter.git", 7 | "scripts": { 8 | "start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js", 9 | "test": "mocha --compilers js:babel-core/register --require ./test/test_helper.js --recursive ./test", 10 | "test:watch": "npm run test -- --watch" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "babel-core": "^6.2.1", 16 | "babel-loader": "^6.2.0", 17 | "babel-preset-es2015": "^6.1.18", 18 | "babel-preset-react": "^6.1.18", 19 | "chai": "^3.5.0", 20 | "chai-jquery": "^2.0.0", 21 | "jquery": "^2.2.1", 22 | "jsdom": "^8.1.0", 23 | "mocha": "^2.4.5", 24 | "react-addons-test-utils": "^0.14.7", 25 | "webpack": "^1.12.9", 26 | "webpack-dev-server": "^1.14.0" 27 | }, 28 | "dependencies": { 29 | "axios": "^0.9.1", 30 | "babel-preset-stage-1": "^6.1.18", 31 | "lodash": "^3.10.1", 32 | "react": "^0.14.3", 33 | "react-dom": "^0.14.3", 34 | "react-redux": "^4.0.0", 35 | "react-router": "^2.0.1", 36 | "redux": "^3.0.4", 37 | "redux-thunk": "^2.0.1" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/src/actions/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export function fetchUsers() { 4 | const request = axios.get('http://jsonplaceholder.typicode.com/users'); 5 | 6 | return (dispatch) => { 7 | request.then(({data}) => { 8 | dispatch({ type: 'FETCH_PROFILES', payload: data }) 9 | }); 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/src/components/app.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import * as actions from '../actions'; 4 | 5 | export default class App extends Component { 6 | componentWillMount() { 7 | this.props.fetchUsers(); 8 | } 9 | 10 | renderUser({id, name, email}) { 11 | return ( 12 |
  • 13 | 14 | {email} 15 | 16 | {name} 17 |
  • 18 | ); 19 | } 20 | 21 | render() { 22 | return ( 23 |
    24 |

    Email Directory

    25 | 28 |
    29 | ); 30 | } 31 | } 32 | 33 | export default connect((state => state), actions)(App); 34 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { createStore, applyMiddleware } from 'redux'; 5 | import reduxThunk from 'redux-thunk'; 6 | 7 | import App from './components/app'; 8 | import reducers from './reducers'; 9 | 10 | const createStoreWithMiddleware = applyMiddleware(reduxThunk)(createStore); 11 | 12 | ReactDOM.render( 13 | 14 | 15 | 16 | , document.querySelector('.container')); 17 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | const rootReducer = combineReducers({ 4 | users: (state = [], action) => action.payload || state 5 | }); 6 | 7 | export default rootReducer; 8 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/style/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/RallyCodingWeekly/acda863ee55fe5af19c3e9e9bceed997dcf0ec0c/002 - Basics of Redux Thunk/style/style.css -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/test/components/app_test.js: -------------------------------------------------------------------------------- 1 | import { renderComponent , expect } from '../test_helper'; 2 | import App from '../../src/components/app'; 3 | 4 | describe('App' , () => { 5 | let component; 6 | 7 | beforeEach(() => { 8 | component = renderComponent(App); 9 | }); 10 | 11 | it('renders something', () => { 12 | expect(component).to.exist; 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/test/test_helper.js: -------------------------------------------------------------------------------- 1 | import _$ from 'jquery'; 2 | import React from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | import TestUtils from 'react-addons-test-utils'; 5 | import jsdom from 'jsdom'; 6 | import chai, { expect } from 'chai'; 7 | import chaiJquery from 'chai-jquery'; 8 | import { Provider } from 'react-redux'; 9 | import { createStore } from 'redux'; 10 | import reducers from '../src/reducers'; 11 | 12 | global.document = jsdom.jsdom(''); 13 | global.window = global.document.defaultView; 14 | const $ = _$(window); 15 | 16 | chaiJquery(chai, chai.util, $); 17 | 18 | function renderComponent(ComponentClass, props = {}, state = {}) { 19 | const componentInstance = TestUtils.renderIntoDocument( 20 | 21 | 22 | 23 | ); 24 | 25 | return $(ReactDOM.findDOMNode(componentInstance)); 26 | } 27 | 28 | $.fn.simulate = function(eventName, value) { 29 | if (value) { 30 | this.val(value); 31 | } 32 | TestUtils.Simulate[eventName](this[0]); 33 | }; 34 | 35 | export {renderComponent, expect}; 36 | -------------------------------------------------------------------------------- /002 - Basics of Redux Thunk/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: [ 3 | './src/index.js' 4 | ], 5 | output: { 6 | path: __dirname, 7 | publicPath: '/', 8 | filename: 'bundle.js' 9 | }, 10 | module: { 11 | loaders: [{ 12 | exclude: /node_modules/, 13 | loader: 'babel' 14 | }] 15 | }, 16 | resolve: { 17 | extensions: ['', '.js', '.jsx'] 18 | }, 19 | devServer: { 20 | historyApiFallback: true, 21 | contentBase: './' 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"] 3 | } 4 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | bundle.js 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/README.md: -------------------------------------------------------------------------------- 1 | # ReduxSimpleStarter 2 | 3 | ###Getting Started### 4 | 5 | There are two methods for getting started with this repo. 6 | 7 | ####Familiar with Git?##### 8 | Checkout this repo, install depdencies, then start the gulp process with the following: 9 | 10 | ``` 11 | > git clone git@github.com:StephenGrider/ReduxSimpleStarter.git 12 | > cd ReduxSimpleStarter 13 | > npm install 14 | > npm start 15 | ``` 16 | 17 | ####Not Familiar with Git?##### 18 | Click [here](https://github.com/StephenGrider/ReactStarter/releases) then download the .zip file. Extract the contents of the zip file, then open your terminal, change to the project directory, and: 19 | 20 | ``` 21 | > npm install 22 | > npm start 23 | ``` 24 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redux-simple-starter", 3 | "version": "1.0.0", 4 | "description": "Simple starter package for Redux with React and Babel support", 5 | "main": "index.js", 6 | "repository": "git@github.com:StephenGrider/ReduxSimpleStarter.git", 7 | "scripts": { 8 | "start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --history-api-fallback" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel-core": "^6.2.1", 14 | "babel-loader": "^6.2.0", 15 | "babel-preset-es2015": "^6.1.18", 16 | "babel-preset-react": "^6.1.18", 17 | "webpack": "^1.12.9", 18 | "webpack-dev-server": "^1.14.0" 19 | }, 20 | "dependencies": { 21 | "axios": "^0.8.1", 22 | "babel-preset-stage-1": "^6.1.18", 23 | "lodash": "^3.10.1", 24 | "react": "^0.14.3", 25 | "react-dom": "^0.14.3", 26 | "react-redux": "^4.0.0", 27 | "react-router": "^2.0.0-rc5", 28 | "redux": "^3.0.4", 29 | "redux-form": "^4.1.3", 30 | "redux-promise": "^0.5.0", 31 | "redux-simple-router": "^2.0.3" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/src/actions/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export const FETCH_POST = 'FETCH_POST'; 4 | export const FETCH_POSTS = 'FETCH_POSTS'; 5 | export const CREATE_POST = 'CREATE_POST'; 6 | export const DELETE_POST = 'DELETE_POST'; 7 | 8 | const ROOT_URL = 'http://reduxblog.herokuapp.com/api'; 9 | const KEY = `?key=ab42`; 10 | 11 | export function fetchPost(id) { 12 | const request = axios.get(`${ROOT_URL}/posts/${id}${KEY}`); 13 | 14 | return { 15 | type: FETCH_POST, 16 | payload: request 17 | }; 18 | } 19 | 20 | export function fetchPosts() { 21 | const request = axios.get(`${ROOT_URL}/posts${KEY}`); 22 | 23 | return { 24 | type: FETCH_POSTS, 25 | payload: request 26 | }; 27 | } 28 | 29 | export function createPost(props) { 30 | const request = axios.post(`${ROOT_URL}/posts${KEY}`, props); 31 | 32 | return { 33 | type: CREATE_POST, 34 | payload: request 35 | }; 36 | } 37 | 38 | export function deletePost(id) { 39 | const request = axios.delete(`${ROOT_URL}/posts/${id}${KEY}`,); 40 | 41 | return { 42 | type: DELETE_POST, 43 | payload: request 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/src/components/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Component } from 'react'; 3 | 4 | export default class App extends Component { 5 | render() { 6 | return ( 7 |
    8 | {this.props.children} 9 |
    10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/src/components/posts_index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { fetchPosts } from '../actions/index'; 4 | import { Link } from 'react-router'; 5 | 6 | class PostIndex extends Component { 7 | componentWillMount() { 8 | this.props.fetchPosts(); 9 | } 10 | 11 | renderPosts() { 12 | return this.props.posts.map((post) => { 13 | return ( 14 |
  • 15 | 16 | {post.categories} 17 | {post.title} 18 | 19 |
  • 20 | ) 21 | }); 22 | } 23 | 24 | render() { 25 | return ( 26 |
    27 |
    28 | 29 | Add a Post 30 | 31 |
    32 |

    Posts

    33 | 36 |
    37 | ); 38 | } 39 | } 40 | 41 | function mapStateToProps(state) { 42 | return { posts: state.posts.all }; 43 | } 44 | 45 | export default connect(mapStateToProps, { fetchPosts })(PostIndex); 46 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/src/components/posts_new.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import React, { Component, PropTypes } from 'react'; 3 | import { reduxForm } from 'redux-form'; 4 | import { Link } from 'react-router'; 5 | 6 | const FIELDS = { 7 | title: { 8 | type: 'input', 9 | label: 'Title for Post' 10 | }, 11 | categories: { 12 | type: 'input', 13 | label: 'Enter some categories for this post' 14 | }, 15 | content: { 16 | type: 'textarea', 17 | label: 'Post Contents' 18 | } 19 | }; 20 | 21 | class PostsNew extends Component { 22 | onSubmit(props) { 23 | alert('Post Submitted'); 24 | } 25 | 26 | renderField(fieldConfig, field) { 27 | const fieldHelper = this.props.fields[field]; 28 | 29 | return ( 30 |
    31 | 32 | 33 |
    34 | {fieldHelper.touched ? fieldHelper.error : ''} 35 |
    36 |
    37 | ); 38 | } 39 | 40 | render() { 41 | const { handleSubmit } = this.props; 42 | 43 | return ( 44 |
    this.onSubmit(props))} > 45 |

    Create A New Post

    46 | {_.map(FIELDS, this.renderField.bind(this))} 47 | 48 | Cancel 49 |
    50 | ); 51 | } 52 | } 53 | 54 | function validate(values) { 55 | const errors = {}; 56 | 57 | _.each(FIELDS, (type, field) => { 58 | if (!values[field]) { 59 | errors[field] = `Enter a ${field}`; 60 | } 61 | }); 62 | 63 | return errors; 64 | } 65 | 66 | export default reduxForm({ 67 | form: 'PostsNew', 68 | fields: _.keys(FIELDS), 69 | validate 70 | })(PostsNew); 71 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/src/components/posts_show.js: -------------------------------------------------------------------------------- 1 | import React, { Component, PropTypes } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { fetchPost, deletePost } from '../actions/index'; 4 | import { Link } from 'react-router'; 5 | 6 | class PostsShow extends Component { 7 | static contextTypes = { 8 | router: PropTypes.object 9 | }; 10 | 11 | componentWillMount() { 12 | this.props.fetchPost(this.props.params.id); 13 | } 14 | 15 | onDeleteClick() { 16 | this.props.deletePost(this.props.params.id) 17 | .then(() => { this.context.router.push('/') }); 18 | } 19 | 20 | render() { 21 | const { post } = this.props; 22 | 23 | if (!post) { 24 | return
    Loading...
    ; 25 | } 26 | 27 | return ( 28 |
    29 | Back To Index 30 | 35 |

    {post.title}

    36 |
    Categories: {post.categories}
    37 |

    {post.content}

    38 |
    39 | ); 40 | } 41 | } 42 | 43 | function mapStateToProps(state) { 44 | return { post: state.posts.post }; 45 | } 46 | 47 | export default connect(mapStateToProps, { fetchPost, deletePost })(PostsShow); 48 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { createStore, applyMiddleware } from 'redux'; 5 | import { Router, browserHistory } from 'react-router'; 6 | import promise from 'redux-promise'; 7 | import reducers from './reducers'; 8 | import routes from './routes'; 9 | 10 | const createStoreWithMiddleware = applyMiddleware( 11 | promise 12 | )(createStore); 13 | 14 | ReactDOM.render( 15 | 16 | 17 | 18 | , document.querySelector('.container')); 19 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import {reducer as formReducer} from 'redux-form'; 3 | import PostsReducer from './reducer_posts'; 4 | 5 | const rootReducer = combineReducers({ 6 | posts: PostsReducer, 7 | form: formReducer 8 | }); 9 | 10 | export default rootReducer; 11 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/src/reducers/reducer_posts.js: -------------------------------------------------------------------------------- 1 | import { FETCH_POSTS, FETCH_POST } from '../actions/index'; 2 | 3 | const INITIAL_STATE = { all: [], post: null }; 4 | 5 | export default function(state = INITIAL_STATE, action) { 6 | switch(action.type) { 7 | case FETCH_POST: 8 | return { ...state, post: action.payload.data }; 9 | case FETCH_POSTS: 10 | return { ...state, all: action.payload.data }; 11 | default: 12 | return state; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/src/routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Route, IndexRoute } from 'react-router'; 3 | import App from './components/app'; 4 | import PostsIndex from './components/posts_index'; 5 | import PostsNew from './components/posts_new.js'; 6 | import PostsShow from './components/posts_show.js'; 7 | 8 | export default ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/style/style.css: -------------------------------------------------------------------------------- 1 | form a { 2 | margin-left: 5px; 3 | } 4 | -------------------------------------------------------------------------------- /003 - Dynamic Forms with Redux Form/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: [ 3 | './src/index.js' 4 | ], 5 | output: { 6 | path: __dirname, 7 | publicPath: '/', 8 | filename: 'bundle.js' 9 | }, 10 | module: { 11 | loaders: [{ 12 | exclude: /node_modules/, 13 | loader: 'babel' 14 | }] 15 | }, 16 | resolve: { 17 | extensions: ['', '.js', '.jsx'] 18 | }, 19 | devServer: { 20 | historyApiFallback: true, 21 | contentBase: './' 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"] 3 | } 4 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | bundle.js 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/README.md: -------------------------------------------------------------------------------- 1 | # ReduxSimpleStarter 2 | 3 | ###Getting Started### 4 | 5 | There are two methods for getting started with this repo. 6 | 7 | ####Familiar with Git?##### 8 | Checkout this repo, install depdencies, then start the gulp process with the following: 9 | 10 | ``` 11 | > git clone git@github.com:StephenGrider/ReduxSimpleStarter.git 12 | > cd ReduxSimpleStarter 13 | > npm install 14 | > npm start 15 | ``` 16 | 17 | ####Not Familiar with Git?##### 18 | Click [here](https://github.com/StephenGrider/ReactStarter/releases) then download the .zip file. Extract the contents of the zip file, then open your terminal, change to the project directory, and: 19 | 20 | ``` 21 | > npm install 22 | > npm start 23 | ``` 24 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redux-simple-starter", 3 | "version": "1.0.0", 4 | "description": "Simple starter package for Redux with React and Babel support", 5 | "main": "index.js", 6 | "repository": "git@github.com:StephenGrider/ReduxSimpleStarter.git", 7 | "scripts": { 8 | "start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel-core": "^6.2.1", 14 | "babel-loader": "^6.2.0", 15 | "babel-preset-es2015": "^6.1.18", 16 | "babel-preset-react": "^6.1.18", 17 | "webpack": "^1.12.9", 18 | "webpack-dev-server": "^1.14.0" 19 | }, 20 | "dependencies": { 21 | "axios": "^0.9.1", 22 | "babel-preset-stage-1": "^6.1.18", 23 | "lodash": "^3.10.1", 24 | "react": "^0.14.3", 25 | "react-dom": "^0.14.3", 26 | "react-redux": "^4.0.0", 27 | "redux": "^3.0.4", 28 | "redux-form": "^4.2.0", 29 | "redux-promise": "^0.5.1", 30 | "reselect": "^2.0.3" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/src/actions/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { 3 | FETCH_POSTS, 4 | SELECT_POST, 5 | DESELECT_POST 6 | } from './types' 7 | 8 | export function fetchPosts() { 9 | const request = axios.get('http://jsonplaceholder.typicode.com/posts'); 10 | 11 | return { 12 | type: FETCH_POSTS, 13 | payload: request 14 | }; 15 | } 16 | 17 | export function selectPost(id) { 18 | return { 19 | type: SELECT_POST, 20 | payload: id 21 | }; 22 | } 23 | 24 | export function deselectPost(id) { 25 | return { 26 | type: DESELECT_POST, 27 | payload: id 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/src/actions/types.js: -------------------------------------------------------------------------------- 1 | export const FETCH_POSTS = 'fetch_posts'; 2 | export const SELECT_POST = 'select_post'; 3 | export const DESELECT_POST = 'deslect_post'; 4 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/src/components/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Component } from 'react'; 3 | 4 | import Posts from 'components/posts_list'; 5 | import SelectedPostsList from 'components/selected_posts_list'; 6 | 7 | export default () => { 8 | return ( 9 |
    10 |

    Selected Posts

    11 | 12 |
    13 |

    All Posts

    14 | 15 |
    16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/src/components/posts_list.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import React, { Component } from 'react'; 3 | import { connect } from 'react-redux'; 4 | import * as actions from 'actions'; 5 | 6 | class PostsList extends Component { 7 | componentWillMount() { 8 | this.props.fetchPosts(); 9 | } 10 | 11 | handlePostSelect({ id }, event) { 12 | const { selectPost, deselectPost } = this.props; 13 | 14 | event.target.checked ? selectPost(id) : deselectPost(id); 15 | } 16 | 17 | renderPost(post) { 18 | console.log(_.contains(this.props.selectedPostIds, post.id)) 19 | return ( 20 |
  • 21 | 25 | {post.title} 26 |
  • 27 | ); 28 | } 29 | 30 | render() { 31 | return ( 32 |
      33 | {_.map(this.props.posts, this.renderPost.bind(this))} 34 |
    35 | ); 36 | } 37 | } 38 | 39 | export default connect(({posts, selectedPostIds}) => ({posts, selectedPostIds}) , actions)(PostsList) 40 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/src/components/selected_posts_list.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import SelectedPostsSelector from 'selectors/selected_posts'; 4 | 5 | const SelectedPostsList = (props) => { 6 | return ( 7 |
      8 | { 9 | props.posts.map(post => { 10 | return
    • {post.title}
    • 11 | }) 12 | } 13 |
    14 | ); 15 | }; 16 | 17 | const mapStateToProps = state => { 18 | return { 19 | posts: SelectedPostsSelector(state) 20 | }; 21 | }; 22 | 23 | export default connect(mapStateToProps)(SelectedPostsList); 24 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { createStore, applyMiddleware, compose } from 'redux'; 5 | import ReduxPromise from 'redux-promise'; 6 | 7 | import reducers from 'reducers'; 8 | import App from 'components/app'; 9 | 10 | const createStoreWithMiddleware = compose( 11 | applyMiddleware(ReduxPromise), 12 | window.devToolsExtension ? window.devToolsExtension() : f => f 13 | )(createStore); 14 | 15 | ReactDOM.render( 16 | 17 | 18 | 19 | , document.querySelector('.container')); 20 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import posts from 'reducers/reducer_posts'; 3 | import selectedPostIds from 'reducers/reducer_selected_posts'; 4 | 5 | const rootReducer = combineReducers({ 6 | posts, 7 | selectedPostIds 8 | }); 9 | 10 | export default rootReducer; 11 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/src/reducers/reducer_posts.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import { FETCH_POSTS } from 'actions/types'; 3 | 4 | export default function(state = {}, action) { 5 | switch(action.type) { 6 | case FETCH_POSTS: 7 | return _.mapKeys(action.payload.data, 'id'); 8 | } 9 | 10 | return state; 11 | } 12 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/src/reducers/reducer_selected_posts.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import { 3 | SELECT_POST, 4 | DESELECT_POST 5 | } from 'actions/types'; 6 | 7 | export default function(state = {}, action) { 8 | switch(action.type) { 9 | case SELECT_POST: 10 | return [ ...state, action.payload ]; 11 | case DESELECT_POST: 12 | return _.without(state, action.payload); 13 | } 14 | 15 | return state; 16 | } 17 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/src/selectors/selected_posts.js: -------------------------------------------------------------------------------- 1 | // Reselect selector 2 | // Takes a list of posts and post Ids, and picks out 3 | // the selected Posts 4 | import _ from 'lodash'; 5 | import { createSelector } from 'reselect'; 6 | 7 | // Create select functions to pick off the pieces of state we care about 8 | // for this calculation 9 | const postsSelector = state => state.posts 10 | const selectedPostsSelector = state => state.selectedPostIds 11 | 12 | const getPosts = (posts, selectedPostIds) => { 13 | const selectedPosts = _.filter( 14 | posts, 15 | post => _.contains(selectedPostIds, post.id) 16 | ); 17 | 18 | return selectedPosts; 19 | }; 20 | 21 | export default createSelector( 22 | postsSelector, // pick off a piece of state 23 | selectedPostsSelector, // pick off a piece of state 24 | getPosts // last argument is the function that has our select logic 25 | ); 26 | -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/style/style.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/RallyCodingWeekly/acda863ee55fe5af19c3e9e9bceed997dcf0ec0c/004 - Logicless Components with Reselect/style/style.css -------------------------------------------------------------------------------- /004 - Logicless Components with Reselect/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: [ 3 | './src/index.js' 4 | ], 5 | output: { 6 | path: __dirname, 7 | publicPath: '/', 8 | filename: 'bundle.js' 9 | }, 10 | module: { 11 | loaders: [{ 12 | exclude: /node_modules/, 13 | loader: 'babel' 14 | }] 15 | }, 16 | resolve: { 17 | root: [ __dirname + '/src' ], 18 | extensions: ['', '.js', '.jsx'] 19 | }, 20 | devServer: { 21 | historyApiFallback: true, 22 | contentBase: './' 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"] 3 | } 4 | 5 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/README.md: -------------------------------------------------------------------------------- 1 | # ReduxSimpleStarter 2 | 3 | Interested in learning [Redux](https://www.udemy.com/react-redux/)? 4 | 5 | ###Getting Started### 6 | 7 | There are two methods for getting started with this repo. 8 | 9 | ####Familiar with Git?##### 10 | Checkout this repo, install depdencies, then start the gulp process with the following: 11 | 12 | ``` 13 | > git clone git@github.com:StephenGrider/ReduxSimpleStarter.git 14 | > cd ReduxSimpleStarter 15 | > npm install 16 | > npm start 17 | ``` 18 | 19 | ####Not Familiar with Git?##### 20 | Click [here](https://github.com/StephenGrider/ReactStarter/releases) then download the .zip file. Extract the contents of the zip file, then open your terminal, change to the project directory, and: 21 | 22 | ``` 23 | > npm install 24 | > npm start 25 | ``` 26 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redux-simple-starter", 3 | "version": "1.0.0", 4 | "description": "Simple starter package for Redux with React and Babel support", 5 | "main": "index.js", 6 | "repository": "git@github.com:StephenGrider/ReduxSimpleStarter.git", 7 | "scripts": { 8 | "start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js", 9 | "test": "mocha --compilers js:babel-core/register --require ./test/test_helper.js --recursive ./test", 10 | "test:watch": "npm run test -- --watch" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "babel-core": "^6.2.1", 16 | "babel-loader": "^6.2.0", 17 | "babel-preset-es2015": "^6.1.18", 18 | "babel-preset-react": "^6.1.18", 19 | "chai": "^3.5.0", 20 | "chai-jquery": "^2.0.0", 21 | "jquery": "^2.2.1", 22 | "jsdom": "^8.1.0", 23 | "mocha": "^2.4.5", 24 | "react-addons-test-utils": "^0.14.7", 25 | "webpack": "^1.12.9", 26 | "webpack-dev-server": "^1.14.0" 27 | }, 28 | "dependencies": { 29 | "axios": "^0.11.0", 30 | "babel-preset-stage-1": "^6.1.18", 31 | "lodash": "^3.10.1", 32 | "react": "^0.14.3", 33 | "react-dom": "^0.14.3", 34 | "react-redux": "^4.4.5", 35 | "react-router": "^2.4.0", 36 | "redux": "^3.0.4", 37 | "redux-promise": "^0.5.3" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/src/actions/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | import { 4 | FETCH_PHOTOS 5 | } from './types'; 6 | 7 | export function fetchPhotos() { 8 | const request = axios.get('http://jsonplaceholder.typicode.com/photos?albumId=41'); 9 | 10 | return { 11 | type: FETCH_PHOTOS, 12 | payload: request 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/src/actions/types.js: -------------------------------------------------------------------------------- 1 | export const FETCH_PHOTOS = 'fetch_photos'; 2 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/src/components/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Component } from 'react'; 3 | 4 | export default class App extends Component { 5 | render() { 6 | return ( 7 |
    {this.props.children}
    8 | ); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/src/components/photos.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { Link } from 'react-router'; 4 | 5 | class UserList extends Component { 6 | renderPhotos() { 7 | return this.props.photos.map(photo => { 8 | return ( 9 | 10 |
  • 11 | 12 |
  • 13 | 14 | ); 15 | }); 16 | } 17 | 18 | render() { 19 | return ( 20 |
      21 | {this.renderPhotos()} 22 |
    23 | ); 24 | } 25 | } 26 | 27 | function mapStateToProps({ photos }) { 28 | return { photos } 29 | } 30 | 31 | export default connect(mapStateToProps)(UserList); 32 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/src/index.js: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom'; 2 | import Routes from './routes'; 3 | 4 | ReactDOM.render(Routes, document.querySelector('.container')); 5 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import photos from './photos_reducer'; 3 | 4 | const rootReducer = combineReducers({ 5 | photos 6 | }); 7 | 8 | export default rootReducer; 9 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/src/reducers/photos_reducer.js: -------------------------------------------------------------------------------- 1 | import { FETCH_PHOTOS } from '../actions/types'; 2 | 3 | export default function(state = [], action) { 4 | switch (action.type) { 5 | case FETCH_PHOTOS: 6 | return action.payload.data; 7 | default: 8 | return state; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/src/routes/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Provider } from 'react-redux'; 3 | import { Router, Route, browserHistory } from 'react-router'; 4 | 5 | import App from '../components/app'; 6 | import Photos from '../components/photos'; 7 | import store from '../store'; 8 | 9 | import { onPhotosEnter } from './route_callbacks'; 10 | 11 | export default ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/src/routes/route_callbacks.js: -------------------------------------------------------------------------------- 1 | import store from '../store'; 2 | import { fetchPhotos } from '../actions'; 3 | 4 | export function onPhotosEnter() { 5 | store.dispatch(fetchPhotos()); 6 | } 7 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/src/store.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from 'redux'; 2 | import reduxPromise from 'redux-promise'; 3 | import reducers from './reducers'; 4 | 5 | const createStoreWithMiddleware = applyMiddleware(reduxPromise)(createStore); 6 | 7 | export default createStoreWithMiddleware(reducers) 8 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/style/style.css: -------------------------------------------------------------------------------- 1 | .list-group-item { 2 | display: inline-block !important; 3 | } 4 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/test/components/app_test.js: -------------------------------------------------------------------------------- 1 | import { renderComponent , expect } from '../test_helper'; 2 | import App from '../../src/components/app'; 3 | 4 | describe('App' , () => { 5 | let component; 6 | 7 | beforeEach(() => { 8 | component = renderComponent(App); 9 | }); 10 | 11 | it('renders something', () => { 12 | expect(component).to.exist; 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/test/test_helper.js: -------------------------------------------------------------------------------- 1 | import _$ from 'jquery'; 2 | import React from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | import TestUtils from 'react-addons-test-utils'; 5 | import jsdom from 'jsdom'; 6 | import chai, { expect } from 'chai'; 7 | import chaiJquery from 'chai-jquery'; 8 | import { Provider } from 'react-redux'; 9 | import { createStore } from 'redux'; 10 | import reducers from '../src/reducers'; 11 | 12 | global.document = jsdom.jsdom(''); 13 | global.window = global.document.defaultView; 14 | const $ = _$(window); 15 | 16 | chaiJquery(chai, chai.util, $); 17 | 18 | function renderComponent(ComponentClass, props = {}, state = {}) { 19 | const componentInstance = TestUtils.renderIntoDocument( 20 | 21 | 22 | 23 | ); 24 | 25 | return $(ReactDOM.findDOMNode(componentInstance)); 26 | } 27 | 28 | $.fn.simulate = function(eventName, value) { 29 | if (value) { 30 | this.val(value); 31 | } 32 | TestUtils.Simulate[eventName](this[0]); 33 | }; 34 | 35 | export {renderComponent, expect}; 36 | -------------------------------------------------------------------------------- /005 - A Better Way to Load Data/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: [ 3 | './src/index.js' 4 | ], 5 | output: { 6 | path: __dirname, 7 | publicPath: '/', 8 | filename: 'bundle.js' 9 | }, 10 | module: { 11 | loaders: [{ 12 | exclude: /node_modules/, 13 | loader: 'babel' 14 | }] 15 | }, 16 | resolve: { 17 | extensions: ['', '.js', '.jsx'] 18 | }, 19 | devServer: { 20 | historyApiFallback: true, 21 | contentBase: './' 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /006 - Animation of React Components/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"] 3 | } 4 | 5 | -------------------------------------------------------------------------------- /006 - Animation of React Components/README.md: -------------------------------------------------------------------------------- 1 | # ReduxSimpleStarter 2 | 3 | Interested in learning [Redux](https://www.udemy.com/react-redux/)? 4 | 5 | ###Getting Started### 6 | 7 | There are two methods for getting started with this repo. 8 | 9 | ####Familiar with Git?##### 10 | Checkout this repo, install depdencies, then start the gulp process with the following: 11 | 12 | ``` 13 | > git clone git@github.com:StephenGrider/ReduxSimpleStarter.git 14 | > cd ReduxSimpleStarter 15 | > npm install 16 | > npm start 17 | ``` 18 | 19 | ####Not Familiar with Git?##### 20 | Click [here](https://github.com/StephenGrider/ReactStarter/releases) then download the .zip file. Extract the contents of the zip file, then open your terminal, change to the project directory, and: 21 | 22 | ``` 23 | > npm install 24 | > npm start 25 | ``` 26 | -------------------------------------------------------------------------------- /006 - Animation of React Components/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /006 - Animation of React Components/npm-debug.log: -------------------------------------------------------------------------------- 1 | 0 info it worked if it ends with ok 2 | 1 verbose cli [ '/usr/local/Cellar/node/5.7.0/bin/node', 3 | 1 verbose cli '/usr/local/bin/npm', 4 | 1 verbose cli 'start' ] 5 | 2 info using npm@3.6.0 6 | 3 info using node@v5.7.0 7 | 4 verbose stack Error: ENOENT: no such file or directory, open '/Users/stephengrider/workspace/rallycoding/casts/prod/006/proj/package.json' 8 | 4 verbose stack at Error (native) 9 | 5 verbose cwd /Users/stephengrider/workspace/rallycoding/casts/prod/006/proj 10 | 6 error Darwin 15.2.0 11 | 7 error argv "/usr/local/Cellar/node/5.7.0/bin/node" "/usr/local/bin/npm" "start" 12 | 8 error node v5.7.0 13 | 9 error npm v3.6.0 14 | 10 error path /Users/stephengrider/workspace/rallycoding/casts/prod/006/proj/package.json 15 | 11 error code ENOENT 16 | 12 error errno -2 17 | 13 error syscall open 18 | 14 error enoent ENOENT: no such file or directory, open '/Users/stephengrider/workspace/rallycoding/casts/prod/006/proj/package.json' 19 | 15 error enoent ENOENT: no such file or directory, open '/Users/stephengrider/workspace/rallycoding/casts/prod/006/proj/package.json' 20 | 15 error enoent This is most likely not a problem with npm itself 21 | 15 error enoent and is related to npm not being able to find a file. 22 | 16 verbose exit [ -2, true ] 23 | -------------------------------------------------------------------------------- /006 - Animation of React Components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redux-simple-starter", 3 | "version": "1.0.0", 4 | "description": "Simple starter package for Redux with React and Babel support", 5 | "main": "index.js", 6 | "repository": "git@github.com:StephenGrider/ReduxSimpleStarter.git", 7 | "scripts": { 8 | "start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js", 9 | "test": "mocha --compilers js:babel-core/register --require ./test/test_helper.js --recursive ./test", 10 | "test:watch": "npm run test -- --watch" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "babel-core": "^6.2.1", 16 | "babel-loader": "^6.2.0", 17 | "babel-preset-es2015": "^6.1.18", 18 | "babel-preset-react": "^6.1.18", 19 | "chai": "^3.5.0", 20 | "chai-jquery": "^2.0.0", 21 | "jquery": "^2.2.1", 22 | "jsdom": "^8.1.0", 23 | "mocha": "^2.4.5", 24 | "react-addons-test-utils": "^0.14.7", 25 | "webpack": "^1.12.9", 26 | "webpack-dev-server": "^1.14.0" 27 | }, 28 | "dependencies": { 29 | "babel-preset-stage-1": "^6.1.18", 30 | "faker": "^3.1.0", 31 | "js-image-generator": "^1.0.2", 32 | "lodash": "^3.10.1", 33 | "react": "^0.14.3", 34 | "react-addons-css-transition-group": "^15.0.2", 35 | "react-dom": "^0.14.3", 36 | "react-redux": "^4.0.0", 37 | "react-router": "^2.0.1", 38 | "redux": "^3.0.4" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /006 - Animation of React Components/src/actions/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/RallyCodingWeekly/acda863ee55fe5af19c3e9e9bceed997dcf0ec0c/006 - Animation of React Components/src/actions/index.js -------------------------------------------------------------------------------- /006 - Animation of React Components/src/components/app.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import React, { Component } from 'react'; 3 | import Faker from 'faker'; 4 | import ReactCSSTransitionGroup from 'react-addons-css-transition-group'; 5 | 6 | export default class App extends Component { 7 | constructor (props) { 8 | super(props); 9 | 10 | this.state = { quotes: [] }; 11 | } 12 | 13 | onAddClick() { 14 | const quote = Faker.lorem.sentence(); 15 | this.setState({ quotes: [ ...this.state.quotes, quote ]}); 16 | } 17 | 18 | onRemoveClick(quote) { 19 | this.setState({ quotes: _.without(this.state.quotes, quote) }); 20 | } 21 | 22 | renderQuotes() { 23 | return this.state.quotes.map((item, index) => { 24 | return ( 25 |
  • 26 | {item} 27 | 28 |
  • 29 | ); 30 | }); 31 | } 32 | 33 | render() { 34 | const transitionOptions = { 35 | transitionName: "fade", 36 | transitionEnterTimeout: 500, 37 | transitionLeaveTimeout: 500 38 | }; 39 | 40 | return ( 41 |
    42 | 43 |
      44 | 45 | {this.renderQuotes()} 46 | 47 |
    48 |
    49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /006 - Animation of React Components/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import { createStore, applyMiddleware } from 'redux'; 5 | 6 | import App from './components/app'; 7 | import reducers from './reducers'; 8 | 9 | const createStoreWithMiddleware = applyMiddleware()(createStore); 10 | 11 | ReactDOM.render( 12 | 13 | 14 | 15 | , document.querySelector('.container')); 16 | -------------------------------------------------------------------------------- /006 - Animation of React Components/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | const rootReducer = combineReducers({ 4 | state: (state = {}) => state 5 | }); 6 | 7 | export default rootReducer; 8 | -------------------------------------------------------------------------------- /006 - Animation of React Components/style/style.css: -------------------------------------------------------------------------------- 1 | img { 2 | width: 200px; 3 | } 4 | 5 | ul { 6 | position: relative; 7 | } 8 | 9 | li { 10 | display: flex !important; 11 | justify-content: space-between; 12 | align-items: center; 13 | position: relative; 14 | } 15 | 16 | /* starting state of animation */ 17 | .fade-enter { 18 | transform: rotateX(90deg) rotateZ(90deg); 19 | opacity: 0; 20 | } 21 | 22 | /* end state of animation */ 23 | .fade-enter-active { 24 | transform: rotateX(0deg) rotateZ(0deg); 25 | opacity: 1.0; 26 | transition: .5s ease-in all; 27 | } 28 | 29 | .fade-leave { 30 | opacity: 1.0; 31 | } 32 | 33 | .fade-leave-active { 34 | opacity: 0; 35 | transition: .5s ease-out all; 36 | } 37 | -------------------------------------------------------------------------------- /006 - Animation of React Components/test/components/app_test.js: -------------------------------------------------------------------------------- 1 | import { renderComponent , expect } from '../test_helper'; 2 | import App from '../../src/components/app'; 3 | 4 | describe('App' , () => { 5 | let component; 6 | 7 | beforeEach(() => { 8 | component = renderComponent(App); 9 | }); 10 | 11 | it('renders something', () => { 12 | expect(component).to.exist; 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /006 - Animation of React Components/test/test_helper.js: -------------------------------------------------------------------------------- 1 | import _$ from 'jquery'; 2 | import React from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | import TestUtils from 'react-addons-test-utils'; 5 | import jsdom from 'jsdom'; 6 | import chai, { expect } from 'chai'; 7 | import chaiJquery from 'chai-jquery'; 8 | import { Provider } from 'react-redux'; 9 | import { createStore } from 'redux'; 10 | import reducers from '../src/reducers'; 11 | 12 | global.document = jsdom.jsdom(''); 13 | global.window = global.document.defaultView; 14 | const $ = _$(window); 15 | 16 | chaiJquery(chai, chai.util, $); 17 | 18 | function renderComponent(ComponentClass, props = {}, state = {}) { 19 | const componentInstance = TestUtils.renderIntoDocument( 20 | 21 | 22 | 23 | ); 24 | 25 | return $(ReactDOM.findDOMNode(componentInstance)); 26 | } 27 | 28 | $.fn.simulate = function(eventName, value) { 29 | if (value) { 30 | this.val(value); 31 | } 32 | TestUtils.Simulate[eventName](this[0]); 33 | }; 34 | 35 | export {renderComponent, expect}; 36 | -------------------------------------------------------------------------------- /006 - Animation of React Components/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: [ 3 | './src/index.js' 4 | ], 5 | output: { 6 | path: __dirname, 7 | publicPath: '/', 8 | filename: 'bundle.js' 9 | }, 10 | module: { 11 | loaders: [{ 12 | exclude: /node_modules/, 13 | loader: 'babel' 14 | }] 15 | }, 16 | resolve: { 17 | extensions: ['', '.js', '.jsx'] 18 | }, 19 | devServer: { 20 | historyApiFallback: true, 21 | contentBase: './' 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /008 - Building Modals with React/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"] 3 | } 4 | -------------------------------------------------------------------------------- /008 - Building Modals with React/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | bundle.js 3 | npm-debug.log 4 | 5 | # IntelliJ 6 | *.iml 7 | /.idea -------------------------------------------------------------------------------- /008 - Building Modals with React/README.md: -------------------------------------------------------------------------------- 1 | # ReduxSimpleStarter 2 | 3 | Interested in learning [Redux](https://www.udemy.com/react-redux/)? 4 | 5 | ###Getting Started### 6 | 7 | There are two methods for getting started with this repo. 8 | 9 | ####Familiar with Git?##### 10 | Checkout this repo, install dependencies, then start the gulp process with the following: 11 | 12 | ``` 13 | > git clone git@github.com:StephenGrider/ReduxSimpleStarter.git 14 | > cd ReduxSimpleStarter 15 | > npm install 16 | > npm start 17 | ``` 18 | 19 | ####Not Familiar with Git?##### 20 | Click [here](https://github.com/StephenGrider/ReactStarter/releases) then download the .zip file. Extract the contents of the zip file, then open your terminal, change to the project directory, and: 21 | 22 | ``` 23 | > npm install 24 | > npm start 25 | ``` 26 | -------------------------------------------------------------------------------- /008 - Building Modals with React/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /008 - Building Modals with React/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redux-simple-starter", 3 | "version": "1.0.0", 4 | "description": "Simple starter package for Redux with React and Babel support", 5 | "main": "index.js", 6 | "repository": "git@github.com:StephenGrider/ReduxSimpleStarter.git", 7 | "scripts": { 8 | "start": "node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js", 9 | "test": "mocha --compilers js:babel-core/register --require ./test/test_helper.js --recursive ./test", 10 | "test:watch": "npm run test -- --watch" 11 | }, 12 | "author": "", 13 | "license": "ISC", 14 | "devDependencies": { 15 | "babel-core": "^6.2.1", 16 | "babel-loader": "^6.2.0", 17 | "babel-preset-es2015": "^6.1.18", 18 | "babel-preset-react": "^6.1.18", 19 | "chai": "^3.5.0", 20 | "chai-jquery": "^2.0.0", 21 | "jquery": "^2.2.1", 22 | "jsdom": "^8.1.0", 23 | "mocha": "^2.4.5", 24 | "react-addons-test-utils": "^0.14.7", 25 | "webpack": "^1.12.9", 26 | "webpack-dev-server": "^1.14.0" 27 | }, 28 | "dependencies": { 29 | "babel-preset-stage-1": "^6.1.18", 30 | "lodash": "^3.10.1", 31 | "react": "^0.14.3", 32 | "react-dom": "^0.14.3", 33 | "react-modal": "^1.3.0", 34 | "react-redux": "^4.0.0", 35 | "react-router": "^2.0.1", 36 | "redux": "^3.0.4" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /008 - Building Modals with React/src/actions/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/RallyCodingWeekly/acda863ee55fe5af19c3e9e9bceed997dcf0ec0c/008 - Building Modals with React/src/actions/index.js -------------------------------------------------------------------------------- /008 - Building Modals with React/src/components/app.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Colors from './colors'; 3 | import BadModal from './bad_modal'; 4 | import Modal from './modal'; 5 | 6 | export default class App extends Component { 7 | render() { 8 | return ( 9 |
    10 |
    11 |

    Hello

    Hello

    Hello

    Hello

    Hello
    12 |
    13 |
    14 |

    Hello

    Hello

    Hello

    Hello

    Hello
    15 |
    16 | 17 |

    A really long amount of Modal Content

    18 |

    Etc.

    19 | 20 |
    21 |
    22 |
    23 |
    24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /008 - Building Modals with React/src/components/bad_modal.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default ({ children }) => { 4 | return ( 5 |
    6 | {children} 7 |
    8 | ); 9 | }; 10 | -------------------------------------------------------------------------------- /008 - Building Modals with React/src/components/colors.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | 4 | const Colors = ({ colors }) => { 5 | return ( 6 |
    7 | {colors.map(color =>

    {color}

    )} 8 |
    9 | ); 10 | }; 11 | 12 | function mapStateToProps({ colors }) { 13 | return { colors }; 14 | } 15 | 16 | export default connect(mapStateToProps)(Colors); 17 | -------------------------------------------------------------------------------- /008 - Building Modals with React/src/components/modal.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { store } from '../index'; 4 | import { Provider } from 'react-redux'; 5 | 6 | class Modal extends Component { 7 | componentDidMount() { 8 | this.modalTarget = document.createElement('div'); 9 | this.modalTarget.className = 'modal'; 10 | document.body.appendChild(this.modalTarget); 11 | this._render(); 12 | } 13 | 14 | componentWillUpdate() { 15 | this._render(); 16 | } 17 | 18 | componentWillUnmount() { 19 | ReactDOM.unmountComponentAtNode(this.modalTarget); 20 | document.body.removeChild(this.modalTarget); 21 | } 22 | 23 | _render() { 24 | ReactDOM.render( 25 | 26 |
    {this.props.children}
    27 |
    , 28 | this.modalTarget 29 | ); 30 | } 31 | 32 | render() { 33 | return