├── SUMMARY.md
├── Appendix02
├── HelloWorldApp
│ ├── .watchmanconfig
│ ├── android
│ │ ├── settings.gradle
│ │ ├── app
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ ├── res
│ │ │ │ ├── values
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ └── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── helloworldapp
│ │ │ │ │ ├── MainActivity.java
│ │ │ │ │ └── MainApplication.java
│ │ │ │ └── AndroidManifest.xml
│ │ ├── gradle
│ │ │ └── wrapper
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ ├── keystores
│ │ │ ├── debug.keystore.properties
│ │ │ └── BUCK
│ │ ├── build.gradle
│ │ └── gradle.properties
│ ├── .buckconfig
│ ├── package.json
│ ├── ios
│ │ ├── HelloWorldApp
│ │ │ ├── AppDelegate.h
│ │ │ ├── main.m
│ │ │ ├── Images.xcassets
│ │ │ │ └── AppIcon.appiconset
│ │ │ │ │ └── Contents.json
│ │ │ └── AppDelegate.m
│ │ └── HelloWorldAppTests
│ │ │ └── Info.plist
│ ├── .gitignore
│ ├── index.ios.js
│ └── index.android.js
├── ReactNativeFirebaseMotto
│ ├── .watchmanconfig
│ ├── src
│ │ ├── store
│ │ │ ├── index.js
│ │ │ └── configureStore.js
│ │ ├── components
│ │ │ ├── Main
│ │ │ │ ├── index.js
│ │ │ │ └── Main.js
│ │ │ ├── ToolBar
│ │ │ │ ├── index.js
│ │ │ │ ├── ToolBar.js
│ │ │ │ └── toolBarStyles.js
│ │ │ ├── ListItem
│ │ │ │ ├── index.js
│ │ │ │ ├── listItemStyles.js
│ │ │ │ └── ListItem.js
│ │ │ ├── ActionButton
│ │ │ │ ├── index.js
│ │ │ │ ├── actionButtonStyles.js
│ │ │ │ └── ActionButton.js
│ │ │ ├── InputModal
│ │ │ │ ├── index.js
│ │ │ │ ├── inputModelStyles.js
│ │ │ │ └── InputModal.js
│ │ │ └── MottoList
│ │ │ │ ├── index.js
│ │ │ │ └── mottoStyles.js
│ │ ├── actions
│ │ │ ├── index.js
│ │ │ ├── uiActions.js
│ │ │ └── mottoActions.js
│ │ ├── containers
│ │ │ ├── InputModalContainer
│ │ │ │ ├── index.js
│ │ │ │ └── InputModalContainer.js
│ │ │ ├── MottoListContainer
│ │ │ │ ├── index.js
│ │ │ │ └── MottoListContainer.js
│ │ │ └── ActionButtonContainer
│ │ │ │ ├── index.js
│ │ │ │ └── ActionButtonContainer.js
│ │ ├── constants
│ │ │ ├── config.js
│ │ │ ├── actionTypes.js
│ │ │ └── models.js
│ │ └── reducers
│ │ │ ├── index.js
│ │ │ ├── ui
│ │ │ └── uiReducers.js
│ │ │ └── data
│ │ │ └── mottoReducers.js
│ ├── android
│ │ ├── settings.gradle
│ │ ├── app
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ ├── res
│ │ │ │ ├── values
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ └── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── reactnativefirebasemotto
│ │ │ │ │ ├── MainActivity.java
│ │ │ │ │ └── MainApplication.java
│ │ │ │ └── AndroidManifest.xml
│ │ ├── keystores
│ │ │ ├── debug.keystore.properties
│ │ │ └── BUCK
│ │ ├── gradle
│ │ │ └── wrapper
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ ├── build.gradle
│ │ └── gradle.properties
│ ├── .babelrc
│ ├── .buckconfig
│ ├── .eslintrc
│ ├── index.android.js
│ ├── ios
│ │ ├── ReactNativeFirebaseMotto
│ │ │ ├── AppDelegate.h
│ │ │ ├── main.m
│ │ │ └── Images.xcassets
│ │ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ └── ReactNativeFirebaseMottoTests
│ │ │ └── Info.plist
│ ├── index.ios.js
│ ├── .gitignore
│ └── package.json
└── images
│ ├── demo-1.png
│ ├── demo-2.png
│ ├── android-1.png
│ ├── android-2.png
│ ├── android-3.png
│ ├── android-4.png
│ ├── flexbox-1.png
│ ├── folder-1.png
│ ├── folder-2.png
│ ├── align-items.png
│ ├── firebase-init.png
│ ├── firebase-landing.png
│ ├── justify-content.png
│ ├── firebase-dashboard.png
│ ├── firebase-database-0.png
│ ├── firebase-database-1.png
│ ├── firebase-database-2.png
│ ├── react-native-logo.png
│ ├── react-native-init-app.png
│ ├── react-native-terminal.png
│ ├── flexbox-flex-direction.png
│ └── react-native-init-app-reload.png
├── .gitignore
├── Appendix03
├── react-redux-test-example
│ ├── test
│ │ ├── actionTest.js
│ │ └── reducerTest.test.js
│ ├── src
│ │ ├── actions
│ │ │ ├── index.js
│ │ │ └── todoActions.js
│ │ ├── components
│ │ │ ├── Main
│ │ │ │ ├── index.js
│ │ │ │ └── Main.js
│ │ │ ├── TodoList
│ │ │ │ ├── index.js
│ │ │ │ └── TodoList.js
│ │ │ └── TodoHeader
│ │ │ │ ├── index.js
│ │ │ │ └── TodoHeader.js
│ │ ├── store
│ │ │ ├── index.js
│ │ │ └── configureStore.js
│ │ ├── containers
│ │ │ ├── TodoListContainer
│ │ │ │ ├── index.js
│ │ │ │ └── TodoListContainer.js
│ │ │ └── TodoHeaderContainer
│ │ │ │ ├── index.js
│ │ │ │ └── TodoHeaderContainer.js
│ │ ├── constants
│ │ │ ├── actionTypes.js
│ │ │ └── models.js
│ │ ├── index.html
│ │ ├── reducers
│ │ │ ├── ui
│ │ │ │ └── uiReducers.js
│ │ │ ├── index.js
│ │ │ └── data
│ │ │ │ └── todoReducers.js
│ │ └── index.js
│ ├── .babelrc
│ ├── .eslintrc
│ ├── README.md
│ ├── dist
│ │ └── index.html
│ ├── webpack.config.js
│ └── package.json
├── react-mocha-test-example
│ ├── test
│ │ ├── mocha.opts
│ │ ├── add.test.js
│ │ ├── promise.test.js
│ │ └── async.test.js
│ ├── src
│ │ ├── components
│ │ │ └── Main
│ │ │ │ ├── index.js
│ │ │ │ └── Main.js
│ │ ├── modules
│ │ │ └── add.js
│ │ ├── index.html
│ │ └── index.js
│ ├── .babelrc
│ ├── .eslintrc
│ ├── webpack.config.js
│ └── package.json
├── react-addons-test-utils-example
│ ├── src
│ │ ├── components
│ │ │ ├── Main
│ │ │ │ ├── index.js
│ │ │ │ └── Main.js
│ │ │ ├── TodoList
│ │ │ │ ├── index.js
│ │ │ │ └── TodoList.js
│ │ │ └── TodoHeader
│ │ │ │ ├── index.js
│ │ │ │ └── TodoHeader.js
│ │ ├── index.html
│ │ └── index.js
│ ├── .babelrc
│ ├── .eslint
│ ├── test
│ │ ├── setup.js
│ │ ├── enzyme
│ │ │ ├── shallowRender.test.js
│ │ │ ├── staticRender.test.js
│ │ │ └── mount.test.js
│ │ ├── shallowRender.test.js
│ │ ├── renderIntoDocument.test.js
│ │ └── shallowRenderProps.test.js
│ ├── webpack.config.js
│ └── package.json
└── images
│ └── mocha.png
├── Ch07
├── react-redux-example
│ ├── src
│ │ ├── actions
│ │ │ ├── index.js
│ │ │ └── todoActions.js
│ │ ├── components
│ │ │ ├── Main
│ │ │ │ ├── index.js
│ │ │ │ └── Main.js
│ │ │ ├── TodoHeader
│ │ │ │ ├── index.js
│ │ │ │ └── TodoHeader.js
│ │ │ └── TodoList
│ │ │ │ ├── index.js
│ │ │ │ └── TodoList.js
│ │ ├── store
│ │ │ ├── index.js
│ │ │ └── configureStore.js
│ │ ├── containers
│ │ │ ├── TodoListContainer
│ │ │ │ ├── index.js
│ │ │ │ └── TodoListContainer.js
│ │ │ └── TodoHeaderContainer
│ │ │ │ ├── index.js
│ │ │ │ └── TodoHeaderContainer.js
│ │ ├── constants
│ │ │ ├── actionTypes.js
│ │ │ └── models.js
│ │ ├── index.html
│ │ ├── reducers
│ │ │ ├── ui
│ │ │ │ └── uiReducers.js
│ │ │ ├── index.js
│ │ │ └── data
│ │ │ │ └── todoReducers.js
│ │ └── index.js
│ ├── .babelrc
│ ├── README.md
│ ├── dist
│ │ └── index.html
│ ├── .eslintrc
│ ├── webpack.config.js
│ └── package.json
├── react-flux-example
│ ├── src
│ │ ├── constants
│ │ │ └── actionTypes.js
│ │ ├── components
│ │ │ ├── TodoList
│ │ │ │ ├── index.js
│ │ │ │ └── TodoList.js
│ │ │ └── TodoHeader
│ │ │ │ ├── index.js
│ │ │ │ └── TodoHeader.js
│ │ ├── index.html
│ │ ├── actions
│ │ │ └── todoActions.js
│ │ ├── dispatcher
│ │ │ └── AppDispatcher.js
│ │ ├── index.js
│ │ └── stores
│ │ │ └── TodoStore.js
│ ├── .babelrc
│ ├── .eslintrc
│ ├── dist
│ │ └── index.html
│ ├── webpack.config.js
│ └── package.json
├── images
│ ├── folder.png
│ ├── flux-demo.png
│ ├── flux-react.png
│ ├── redux-flow.png
│ ├── redux-logo.png
│ ├── react-flux.jpeg
│ ├── redux-folder.png
│ ├── redux-store.png
│ ├── using-redux.jpg
│ ├── redux-flowchart.png
│ ├── react-redux-demo.png
│ ├── flux-simple-diagram.png
│ ├── react-flux-diagram.png
│ ├── react-redux-dev-demo.png
│ ├── react-redux-diagram.png
│ └── using-redux-compare.jpg
└── README.md
├── cover.png
├── Ch05
├── react-router-example
│ ├── res
│ │ └── styles
│ │ │ └── main.css
│ ├── src
│ │ ├── components
│ │ │ ├── App
│ │ │ │ ├── index.js
│ │ │ │ ├── appStyles.js
│ │ │ │ └── App.js
│ │ │ ├── Home
│ │ │ │ ├── index.js
│ │ │ │ └── Home.js
│ │ │ ├── User
│ │ │ │ ├── index.js
│ │ │ │ └── User.js
│ │ │ ├── About
│ │ │ │ ├── index.js
│ │ │ │ └── About.js
│ │ │ ├── NavLink
│ │ │ │ ├── index.js
│ │ │ │ └── NavLink.js
│ │ │ ├── Repos
│ │ │ │ ├── index.js
│ │ │ │ └── Repos.js
│ │ │ └── Contacts
│ │ │ │ ├── index.js
│ │ │ │ └── Contacts.js
│ │ ├── index.html
│ │ └── index.js
│ ├── .babelrc
│ ├── .eslintrc
│ ├── webpack.config.js
│ └── package.json
├── images
│ ├── example.png
│ ├── folder.png
│ └── react-router.jpg
└── README.md
├── Ch09
├── react-router-redux-github-finder
│ ├── README.md
│ ├── src
│ │ ├── components
│ │ │ ├── Main
│ │ │ │ ├── index.js
│ │ │ │ └── Main.js
│ │ │ ├── HomePage
│ │ │ │ ├── index.js
│ │ │ │ └── HomePage.js
│ │ │ ├── GithubBox
│ │ │ │ ├── index.js
│ │ │ │ └── GithubBox.js
│ │ │ └── ResultPage
│ │ │ │ ├── index.js
│ │ │ │ └── ResultPage.js
│ │ ├── store
│ │ │ ├── index.js
│ │ │ └── configureStore.js
│ │ ├── actions
│ │ │ ├── index.js
│ │ │ ├── uiActions.js
│ │ │ └── githubActions.js
│ │ ├── containers
│ │ │ ├── HomePageContainer
│ │ │ │ ├── index.js
│ │ │ │ └── HomePageContainer.js
│ │ │ └── ResultPageContainer
│ │ │ │ ├── index.js
│ │ │ │ └── ResultPageContainer.js
│ │ ├── constants
│ │ │ ├── models.js
│ │ │ └── actionTypes.js
│ │ ├── index.html
│ │ ├── reducers
│ │ │ ├── index.js
│ │ │ ├── ui
│ │ │ │ └── uiReducers.js
│ │ │ └── data
│ │ │ │ └── githubReducers.js
│ │ └── index.js
│ ├── .babelrc
│ ├── res
│ │ └── images
│ │ │ └── github.png
│ ├── dist
│ │ └── index.html
│ ├── .eslintrc
│ ├── webpack.config.js
│ └── package.json
├── images
│ ├── demo-1.png
│ └── demo-2.png
└── README.md
├── cc-by-nc-sa.png
├── Ch03
├── todo-examples
│ ├── app
│ │ ├── components
│ │ │ ├── TodoList
│ │ │ │ ├── index.js
│ │ │ │ ├── todoListStyles.js
│ │ │ │ └── TodoList.js
│ │ │ └── TodoHeader
│ │ │ │ ├── index.js
│ │ │ │ ├── todoHeaderStyles.js
│ │ │ │ └── TodoHeader.js
│ │ ├── index.html
│ │ └── index.js
│ ├── .babelrc
│ ├── dist
│ │ └── index.html
│ ├── .eslintrc.js
│ ├── gulpfile.js
│ ├── webpack.config.js
│ ├── .gitignore
│ └── package.json
├── images
│ ├── fb_like.jpg
│ ├── reactjs.png
│ └── component.png
└── README.md
├── Ch02
├── images
│ ├── react.png
│ ├── hello-world.png
│ ├── react-browserify-gulp.png
│ ├── webpack-module-bundler.png
│ ├── browserify-folder-pregulp.png
│ ├── react-webpack-browserify.png
│ └── browserify-folder-possgulp.png
├── browserify-example
│ ├── .babelrc
│ ├── index.html
│ ├── dist
│ │ └── index.html
│ ├── app
│ │ └── index.js
│ └── package.json
├── webpack-example
│ ├── .babelrc
│ ├── app
│ │ ├── index.html
│ │ └── index.js
│ ├── dist
│ │ └── index.html
│ ├── package.json
│ └── webpack.config.js
├── README.md
└── cdn-example
│ └── hello.html
├── Ch10
├── react-redux-server-rendering
│ ├── common
│ │ ├── actions
│ │ │ ├── index.js
│ │ │ └── counterActions.js
│ │ ├── store
│ │ │ ├── index.js
│ │ │ └── configureStore.js
│ │ ├── components
│ │ │ └── Counter
│ │ │ │ ├── index.js
│ │ │ │ └── Counter.js
│ │ ├── containers
│ │ │ └── CounterContainer
│ │ │ │ ├── index.js
│ │ │ │ └── CounterContainer.js
│ │ ├── constants
│ │ │ ├── actionTypes.js
│ │ │ └── models.js
│ │ ├── reducers
│ │ │ ├── index.js
│ │ │ └── counterReducers.js
│ │ └── api
│ │ │ └── counter.js
│ ├── .babelrc
│ ├── server
│ │ └── index.js
│ ├── .eslintrc
│ ├── README.md
│ ├── client
│ │ └── index.js
│ ├── webpack.config.js
│ └── package.json
├── images
│ ├── client-mvc.png
│ ├── isomorphic-api.png
│ ├── client-server-mvc.png
│ ├── open-cook-demo-1.png
│ ├── open-cook-demo-2.png
│ ├── open-cook-demo-3.png
│ ├── open-cook-demo-4.png
│ ├── isomorphic-javascript.png
│ ├── open-cook-demo-folder.png
│ ├── react-server-rendering-demo.png
│ └── react-server-rendering-folder.png
├── react-router-redux-node-isomorphic-open-cook
│ ├── src
│ │ ├── common
│ │ │ ├── components
│ │ │ │ ├── Main
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── Main.js
│ │ │ │ ├── AppBar
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── AppBar.js
│ │ │ │ ├── CheckAuth
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── CheckAuth.js
│ │ │ │ ├── HomePage
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── HomePage.js
│ │ │ │ ├── LoginBox
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── LoginBox.js
│ │ │ │ ├── LoginPage
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── LoginPage.js
│ │ │ │ ├── RecipeBox
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── RecipeBox.js
│ │ │ │ ├── ShareBox
│ │ │ │ │ └── index.js
│ │ │ │ └── SharePage
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── SharePage.js
│ │ │ ├── store
│ │ │ │ ├── index.js
│ │ │ │ └── configureStore.js
│ │ │ ├── containers
│ │ │ │ ├── AppBarContainer
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── AppBarContainer.js
│ │ │ │ ├── HomePageContainer
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── HomePageContainer.js
│ │ │ │ ├── LoginBoxContainer
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── LoginBoxContainer.js
│ │ │ │ ├── LoginPageContainer
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── LoginPageContainer.js
│ │ │ │ ├── RecipeBoxContainer
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── RecipeBoxContainer.js
│ │ │ │ ├── ShareBoxContainer
│ │ │ │ │ └── index.js
│ │ │ │ └── SharePageContainer
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── SharePageContainer.js
│ │ │ ├── actions
│ │ │ │ ├── index.js
│ │ │ │ ├── uiActions.js
│ │ │ │ ├── recipeActions.js
│ │ │ │ └── userActions.js
│ │ │ ├── utils
│ │ │ │ └── fetchComponentData.js
│ │ │ ├── reducers
│ │ │ │ ├── index.js
│ │ │ │ ├── data
│ │ │ │ │ ├── recipeReducers.js
│ │ │ │ │ └── userReducers.js
│ │ │ │ └── ui
│ │ │ │ │ └── uiReducers.js
│ │ │ ├── constants
│ │ │ │ ├── models.js
│ │ │ │ └── actionTypes.js
│ │ │ └── routes
│ │ │ │ └── index.js
│ │ ├── server
│ │ │ ├── index.js
│ │ │ ├── config
│ │ │ │ └── index.js
│ │ │ ├── public
│ │ │ │ └── images
│ │ │ │ │ └── loading.gif
│ │ │ └── models
│ │ │ │ ├── user.js
│ │ │ │ └── recipe.js
│ │ └── client
│ │ │ └── index.js
│ ├── .babelrc
│ ├── .eslintrc
│ └── webpack.config.js
└── README.md
├── Ch01
├── images
│ ├── frameworks.png
│ ├── html-css-js.png
│ └── react-eco-wp.gif
└── README.md
├── Ch06
├── images
│ └── immutable.png
└── README.md
├── Appendix01
└── images
│ └── react-es6.jpg
├── Ch04
├── images
│ └── react-lifecycle.png
└── README.md
├── Appendix04
├── graphql-example
│ ├── .babelrc
│ ├── index.js
│ ├── .eslintrc
│ ├── data.json
│ └── package.json
└── images
│ ├── graphql-demo-1.png
│ ├── graphql-demo-2.png
│ ├── relay-graphql.png
│ └── relay-architecture.png
└── Ch08
└── README.md
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | bower_components/
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/test/actionTest.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/test/reducerTest.test.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/actions/index.js:
--------------------------------------------------------------------------------
1 | export * from './todoActions';
--------------------------------------------------------------------------------
/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/cover.png
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --watch
2 | --reporter spec
3 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/res/styles/main.css:
--------------------------------------------------------------------------------
1 | .active {
2 | color: orange;
3 | }
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/README.md:
--------------------------------------------------------------------------------
1 | # React Router Redux Github Finder
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/actions/index.js:
--------------------------------------------------------------------------------
1 | export * from './todoActions';
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/components/Main/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Main';
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/store/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './configureStore';
--------------------------------------------------------------------------------
/cc-by-nc-sa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/cc-by-nc-sa.png
--------------------------------------------------------------------------------
/Ch03/todo-examples/app/components/TodoList/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoList';
2 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/App/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './App';
2 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/Home/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Home';
2 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/User/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './User';
2 |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/src/constants/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const ADD_TODO = 'ADD_TODO';
2 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/store/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './configureStore';
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/components/Main/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Main';
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/store/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './configureStore';
--------------------------------------------------------------------------------
/Ch02/images/react.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch02/images/react.png
--------------------------------------------------------------------------------
/Ch03/todo-examples/app/components/TodoHeader/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoHeader';
2 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/About/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './About';
2 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/NavLink/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './NavLink';
2 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/Repos/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Repos';
2 |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/src/components/TodoList/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoList';
2 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/components/TodoHeader/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoHeader';
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/components/TodoList/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoList';
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/actions/index.js:
--------------------------------------------------------------------------------
1 | export * from './counterActions';
2 |
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/store/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './configureStore';
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/Main/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Main';
2 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/ToolBar/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './ToolBar';
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/src/components/Main/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Main';
2 |
--------------------------------------------------------------------------------
/Ch03/images/fb_like.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch03/images/fb_like.jpg
--------------------------------------------------------------------------------
/Ch03/images/reactjs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch03/images/reactjs.png
--------------------------------------------------------------------------------
/Ch05/images/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch05/images/example.png
--------------------------------------------------------------------------------
/Ch05/images/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch05/images/folder.png
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/Contacts/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Contacts';
2 |
--------------------------------------------------------------------------------
/Ch07/images/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/folder.png
--------------------------------------------------------------------------------
/Ch07/react-flux-example/src/components/TodoHeader/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoHeader';
2 |
--------------------------------------------------------------------------------
/Ch09/images/demo-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch09/images/demo-1.png
--------------------------------------------------------------------------------
/Ch09/images/demo-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch09/images/demo-2.png
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/ListItem/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './ListItem';
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/src/components/Main/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Main';
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/components/TodoList/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoList';
--------------------------------------------------------------------------------
/Ch01/images/frameworks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch01/images/frameworks.png
--------------------------------------------------------------------------------
/Ch03/images/component.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch03/images/component.png
--------------------------------------------------------------------------------
/Ch06/images/immutable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch06/images/immutable.png
--------------------------------------------------------------------------------
/Ch07/images/flux-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/flux-demo.png
--------------------------------------------------------------------------------
/Ch07/images/flux-react.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/flux-react.png
--------------------------------------------------------------------------------
/Ch07/images/redux-flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/redux-flow.png
--------------------------------------------------------------------------------
/Ch07/images/redux-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/redux-logo.png
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/components/Main/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Main';
2 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/store/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './configureStore';
2 |
--------------------------------------------------------------------------------
/Ch10/images/client-mvc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/client-mvc.png
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/components/Counter/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Counter';
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'HelloWorldApp'
2 |
3 | include ':app'
4 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/ActionButton/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './ActionButton';
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/InputModal/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './InputModal';
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/MottoList/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './MottoList';
2 |
--------------------------------------------------------------------------------
/Appendix02/images/demo-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/demo-1.png
--------------------------------------------------------------------------------
/Appendix02/images/demo-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/demo-2.png
--------------------------------------------------------------------------------
/Appendix03/images/mocha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix03/images/mocha.png
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/src/components/TodoList/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoList';
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/components/TodoHeader/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoHeader';
--------------------------------------------------------------------------------
/Ch01/images/html-css-js.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch01/images/html-css-js.png
--------------------------------------------------------------------------------
/Ch01/images/react-eco-wp.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch01/images/react-eco-wp.gif
--------------------------------------------------------------------------------
/Ch02/images/hello-world.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch02/images/hello-world.png
--------------------------------------------------------------------------------
/Ch05/images/react-router.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch05/images/react-router.jpg
--------------------------------------------------------------------------------
/Ch07/images/react-flux.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/react-flux.jpeg
--------------------------------------------------------------------------------
/Ch07/images/redux-folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/redux-folder.png
--------------------------------------------------------------------------------
/Ch07/images/redux-store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/redux-store.png
--------------------------------------------------------------------------------
/Ch07/images/using-redux.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/using-redux.jpg
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/containers/TodoListContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoListContainer';
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/components/HomePage/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './HomePage';
2 |
--------------------------------------------------------------------------------
/Appendix01/images/react-es6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix01/images/react-es6.jpg
--------------------------------------------------------------------------------
/Appendix02/images/android-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/android-1.png
--------------------------------------------------------------------------------
/Appendix02/images/android-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/android-2.png
--------------------------------------------------------------------------------
/Appendix02/images/android-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/android-3.png
--------------------------------------------------------------------------------
/Appendix02/images/android-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/android-4.png
--------------------------------------------------------------------------------
/Appendix02/images/flexbox-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/flexbox-1.png
--------------------------------------------------------------------------------
/Appendix02/images/folder-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/folder-1.png
--------------------------------------------------------------------------------
/Appendix02/images/folder-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/folder-2.png
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/src/components/TodoHeader/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoHeader';
--------------------------------------------------------------------------------
/Ch02/browserify-example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Ch04/images/react-lifecycle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch04/images/react-lifecycle.png
--------------------------------------------------------------------------------
/Ch07/images/redux-flowchart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/redux-flowchart.png
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/containers/TodoHeaderContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoHeaderContainer';
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/components/GithubBox/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './GithubBox';
2 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/components/ResultPage/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './ResultPage';
2 |
--------------------------------------------------------------------------------
/Ch10/images/isomorphic-api.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/isomorphic-api.png
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/Main/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './Main';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/store/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './configureStore';
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/actions/index.js:
--------------------------------------------------------------------------------
1 | export * from './uiActions';
2 | export * from './mottoActions';
--------------------------------------------------------------------------------
/Appendix02/images/align-items.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/align-items.png
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/containers/TodoListContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoListContainer';
--------------------------------------------------------------------------------
/Appendix04/graphql-example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Ch02/webpack-example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Ch05/react-router-example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Ch07/images/react-redux-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/react-redux-demo.png
--------------------------------------------------------------------------------
/Ch07/react-flux-example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Ch07/react-redux-example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Ch10/images/client-server-mvc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/client-server-mvc.png
--------------------------------------------------------------------------------
/Ch10/images/open-cook-demo-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/open-cook-demo-1.png
--------------------------------------------------------------------------------
/Ch10/images/open-cook-demo-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/open-cook-demo-2.png
--------------------------------------------------------------------------------
/Ch10/images/open-cook-demo-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/open-cook-demo-3.png
--------------------------------------------------------------------------------
/Ch10/images/open-cook-demo-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/open-cook-demo-4.png
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/containers/CounterContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './CounterContainer';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/AppBar/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './AppBar';
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/containers/InputModalContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './InputModalContainer';
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/containers/MottoListContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './MottoListContainer';
--------------------------------------------------------------------------------
/Appendix02/images/firebase-init.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/firebase-init.png
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/src/modules/add.js:
--------------------------------------------------------------------------------
1 | const add = (x, y) => (
2 | x + y
3 | );
4 |
5 | export default add;
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/containers/TodoHeaderContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './TodoHeaderContainer';
--------------------------------------------------------------------------------
/Appendix04/images/graphql-demo-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix04/images/graphql-demo-1.png
--------------------------------------------------------------------------------
/Appendix04/images/graphql-demo-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix04/images/graphql-demo-2.png
--------------------------------------------------------------------------------
/Appendix04/images/relay-graphql.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix04/images/relay-graphql.png
--------------------------------------------------------------------------------
/Ch07/images/flux-simple-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/flux-simple-diagram.png
--------------------------------------------------------------------------------
/Ch07/images/react-flux-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/react-flux-diagram.png
--------------------------------------------------------------------------------
/Ch07/images/react-redux-dev-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/react-redux-dev-demo.png
--------------------------------------------------------------------------------
/Ch07/images/react-redux-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/react-redux-diagram.png
--------------------------------------------------------------------------------
/Ch07/images/using-redux-compare.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch07/images/using-redux-compare.jpg
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/actions/index.js:
--------------------------------------------------------------------------------
1 | export * from './uiActions';
2 | export * from './githubActions';
3 |
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/CheckAuth/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './CheckAuth';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/HomePage/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './HomePage';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/LoginBox/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './LoginBox';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/LoginPage/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './LoginPage';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/RecipeBox/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './RecipeBox';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/ShareBox/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './ShareBox';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/SharePage/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './SharePage';
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'ReactNativeFirebaseMotto'
2 |
3 | include ':app'
4 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/containers/ActionButtonContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './ActionButtonContainer';
--------------------------------------------------------------------------------
/Appendix02/images/firebase-landing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/firebase-landing.png
--------------------------------------------------------------------------------
/Appendix02/images/justify-content.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/justify-content.png
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Ch02/images/react-browserify-gulp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch02/images/react-browserify-gulp.png
--------------------------------------------------------------------------------
/Ch02/images/webpack-module-bundler.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch02/images/webpack-module-bundler.png
--------------------------------------------------------------------------------
/Ch03/todo-examples/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/App/appStyles.js:
--------------------------------------------------------------------------------
1 | export default {
2 | active: {
3 | color: 'red',
4 | },
5 | };
6 |
--------------------------------------------------------------------------------
/Ch10/images/isomorphic-javascript.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/isomorphic-javascript.png
--------------------------------------------------------------------------------
/Ch10/images/open-cook-demo-folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/open-cook-demo-folder.png
--------------------------------------------------------------------------------
/Appendix02/images/firebase-dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/firebase-dashboard.png
--------------------------------------------------------------------------------
/Appendix02/images/firebase-database-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/firebase-database-0.png
--------------------------------------------------------------------------------
/Appendix02/images/firebase-database-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/firebase-database-1.png
--------------------------------------------------------------------------------
/Appendix02/images/firebase-database-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/firebase-database-2.png
--------------------------------------------------------------------------------
/Appendix02/images/react-native-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/react-native-logo.png
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Appendix04/images/relay-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix04/images/relay-architecture.png
--------------------------------------------------------------------------------
/Ch02/images/browserify-folder-pregulp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch02/images/browserify-folder-pregulp.png
--------------------------------------------------------------------------------
/Ch02/images/react-webpack-browserify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch02/images/react-webpack-browserify.png
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/containers/HomePageContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './HomePageContainer';
2 |
3 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/containers/ResultPageContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './ResultPageContainer';
2 |
--------------------------------------------------------------------------------
/Appendix02/images/react-native-init-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/react-native-init-app.png
--------------------------------------------------------------------------------
/Appendix02/images/react-native-terminal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/react-native-terminal.png
--------------------------------------------------------------------------------
/Ch02/images/browserify-folder-possgulp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch02/images/browserify-folder-possgulp.png
--------------------------------------------------------------------------------
/Ch10/images/react-server-rendering-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/react-server-rendering-demo.png
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/AppBarContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './AppBarContainer';
--------------------------------------------------------------------------------
/Appendix02/images/flexbox-flex-direction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/flexbox-flex-direction.png
--------------------------------------------------------------------------------
/Ch03/todo-examples/app/components/TodoHeader/todoHeaderStyles.js:
--------------------------------------------------------------------------------
1 | export default {
2 | todoHeader: {
3 | color: 'red',
4 | },
5 | };
6 |
7 |
--------------------------------------------------------------------------------
/Ch03/todo-examples/app/components/TodoList/todoListStyles.js:
--------------------------------------------------------------------------------
1 | export default {
2 | todoHeader: {
3 | color: 'red',
4 | },
5 | };
6 |
7 |
--------------------------------------------------------------------------------
/Ch10/images/react-server-rendering-folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/images/react-server-rendering-folder.png
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | ],
6 | "plugins": []
7 | }
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/HomePageContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './HomePageContainer';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/LoginBoxContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './LoginBoxContainer';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/LoginPageContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './LoginPageContainer';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/RecipeBoxContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './RecipeBoxContainer';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/ShareBoxContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './ShareBoxContainer';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/SharePageContainer/index.js:
--------------------------------------------------------------------------------
1 | export { default } from './SharePageContainer';
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | "react-native"
6 | ],
7 | "plugins": []
8 | }
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | HelloWorldApp
3 |
4 |
--------------------------------------------------------------------------------
/Appendix02/images/react-native-init-app-reload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/images/react-native-init-app-reload.png
--------------------------------------------------------------------------------
/Ch05/README.md:
--------------------------------------------------------------------------------
1 | # Ch05 React Router
2 |
3 | 1. [React Router 入门实战教学](react-router-introduction.md)
4 |
5 | ## :door: 任意门
6 | | [回首页](../../../tree/zh-CN/) |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "no-multiple-empty-lines": [2, {"max": 2, "maxEOF": 2}]
5 | }
6 | }
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/server/index.js:
--------------------------------------------------------------------------------
1 | // use babel-register to precompile ES6 syntax
2 | require('babel-register');
3 | require('./server');
4 |
--------------------------------------------------------------------------------
/Ch06/README.md:
--------------------------------------------------------------------------------
1 | # Ch06 ImmutableJS
2 |
3 | 1. [ImmutableJS 入门教学](../Ch06/react-immutable-introduction.md)
4 |
5 | ## :door: 任意门
6 | | [回首页](../../../tree/zh-CN/) |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react",
5 | "babel-preset-stage-1",
6 | ],
7 | "plugins": []
8 | }
--------------------------------------------------------------------------------
/Appendix04/graphql-example/index.js:
--------------------------------------------------------------------------------
1 | //index.js
2 | //require `babel/register` to handle JavaScript code
3 | require('babel/register');
4 | require('./server.js');
5 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/Home/Home.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Home = () => (
4 |
Home
5 | );
6 |
7 | export default Home;
8 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/User/User.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const User = () => (
4 | User
5 | );
6 |
7 | export default User;
8 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/.buckconfig:
--------------------------------------------------------------------------------
1 |
2 | [android]
3 | target = Google Inc.:Google APIs:23
4 |
5 | [maven_repositories]
6 | central = https://repo1.maven.org/maven2
7 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ReactNativeFirebaseMotto
3 |
4 |
--------------------------------------------------------------------------------
/Ch02/README.md:
--------------------------------------------------------------------------------
1 | # Ch02 React 开发环境设置与 Webpack 入门
2 |
3 | 1. [React 开发环境设置与 Webpack 入门](../Ch02/webpack-dev-enviroment.md)
4 |
5 | ## :door: 任意门
6 | | [回首页](../../../tree/zh-CN/) |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/About/About.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const About = () => (
4 | About
5 | );
6 |
7 | export default About;
8 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/res/images/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch09/react-router-redux-github-finder/res/images/github.png
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/constants/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const INCREMENT_COUNT = 'INCREMENT_COUNT';
2 | export const DECREMENT_COUNT = 'DECREMENT_COUNT';
3 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/actions/index.js:
--------------------------------------------------------------------------------
1 | export * from './userActions';
2 | export * from './recipeActions';
3 | export * from './uiActions';
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/server/index.js:
--------------------------------------------------------------------------------
1 | // use babel-register to precompile ES6 syntax
2 | require('babel-register');
3 | require('./server');
4 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/server/config/index.js:
--------------------------------------------------------------------------------
1 | export default ({
2 | "secret": "ilovecooking",
3 | "database": "mongodb://localhost/open_cook"
4 | });
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/HelloWorldApp/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/.buckconfig:
--------------------------------------------------------------------------------
1 |
2 | [android]
3 | target = Google Inc.:Google APIs:23
4 |
5 | [maven_repositories]
6 | central = https://repo1.maven.org/maven2
7 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/constants/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const CREATE_TODO = 'CREATE_TODO';
2 | export const DELETE_TODO = 'DELETE_TODO';
3 | export const CHANGE_TEXT = 'CHANGE_TEXT';
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/keystores/debug.keystore.properties:
--------------------------------------------------------------------------------
1 | key.store=debug.keystore
2 | key.alias=androiddebugkey
3 | key.store.password=android
4 | key.alias.password=android
5 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/Contacts/Contacts.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Contacts = () => (
4 | Contacts
5 | );
6 |
7 | export default Contacts;
8 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/constants/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const CREATE_TODO = 'CREATE_TODO';
2 | export const DELETE_TODO = 'DELETE_TODO';
3 | export const CHANGE_TEXT = 'CHANGE_TEXT';
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/keystores/debug.keystore.properties:
--------------------------------------------------------------------------------
1 | key.store=debug.keystore
2 | key.alias=androiddebugkey
3 | key.store.password=android
4 | key.alias.password=android
5 |
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/constants/models.js:
--------------------------------------------------------------------------------
1 | import Immutable from 'immutable';
2 |
3 | // initstate model
4 | export const CounterState = Immutable.Record({
5 | count: 0,
6 | });
7 |
8 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/HelloWorldApp/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/HelloWorldApp/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/HelloWorldApp/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/ReactNativeFirebaseMotto/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/Ch01/README.md:
--------------------------------------------------------------------------------
1 | # Ch01 前端工程简介和 React 生态系简介
2 |
3 | 1. [Web 前端工程入门简介](front-end-introduction.md)
4 | 2. [React 生态系入门简介](react-ecosystem-introduction.md)
5 |
6 | ## :door: 任意门
7 | | [回首页](../../../tree/zh-CN/) |
--------------------------------------------------------------------------------
/Ch08/README.md:
--------------------------------------------------------------------------------
1 | # Ch08 Container 与 Presentational Components
2 |
3 | 1. [Container 与 Presentational Components 入门](container-presentational-component-.md)
4 |
5 | ## :door: 任意门
6 | | [回首页](../../../tree/zh-CN/) |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/HelloWorldApp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/keystores/BUCK:
--------------------------------------------------------------------------------
1 | keystore(
2 | name = 'debug',
3 | store = 'debug.keystore',
4 | properties = 'debug.keystore.properties',
5 | visibility = [
6 | 'PUBLIC',
7 | ],
8 | )
9 |
--------------------------------------------------------------------------------
/Appendix04/graphql-example/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
5 | },
6 | "env" :{
7 | "es6": true
8 | }
9 | }
--------------------------------------------------------------------------------
/Ch05/react-router-example/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
5 | },
6 | "env" :{
7 | "browser": true,
8 | }
9 | }
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/keystores/BUCK:
--------------------------------------------------------------------------------
1 | keystore(
2 | name = 'debug',
3 | store = 'debug.keystore',
4 | properties = 'debug.keystore.properties',
5 | visibility = [
6 | 'PUBLIC',
7 | ],
8 | )
9 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/constants/config.js:
--------------------------------------------------------------------------------
1 | export const firebaseConfig = {
2 | apiKey: "apiKey",
3 | authDomain: "authDomain",
4 | databaseURL: "databaseURL",
5 | storageBucket: "storageBucket",
6 | };
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Redux Todo
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/server/public/images/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Ch10/react-router-redux-node-isomorphic-open-cook/src/server/public/images/loading.gif
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
5 | },
6 | "env" :{
7 | "browser": true,
8 | }
9 | }
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
5 | },
6 | "env" :{
7 | "browser": true,
8 | }
9 | }
--------------------------------------------------------------------------------
/Ch03/README.md:
--------------------------------------------------------------------------------
1 | # Ch03 React/JSX/Component 简介
2 |
3 | 1. [ReactJS 与 Component 入门介绍](../Ch03/reactjs-introduction.md)
4 | 2. [JSX 简明入门教学指南](../Ch03/react-jsx-introduction.md)
5 |
6 | ## :door: 任意门
7 | | [回首页](../../../tree/zh-CN/) |
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
5 | },
6 | "env" :{
7 | "browser": true,
8 | }
9 | }
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/carlleton/reactjs101/HEAD/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Test
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Redux Todo
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | TodoFlux
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Ch09/README.md:
--------------------------------------------------------------------------------
1 | # Ch09 用 React + Router + Redux + ImmutableJS 写一个 Github 查询应用
2 |
3 | 1. [用 React + Router + Redux + ImmutableJS 写一个 Github 查询应用](react-router-redux-github-finder.md)
4 |
5 | ## :door: 任意门
6 | | [回首页](../../../tree/zh-CN/) |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/actions/uiActions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions';
2 | import {
3 | TOGGLE_MODAL,
4 | } from '../constants/actionTypes';
5 |
6 | export const toggleModal = createAction('TOGGLE_MODAL');
7 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import Main from './components/Main';
4 |
5 | ReactDOM.render(
6 | ,
7 | document.getElementById('app')
8 | );
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | React Mocha Test
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
5 | },
6 | "env" :{
7 | "browser": true,
8 | }
9 | }
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/constants/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const GET_MOTTOS = 'GET_MOTTOS';
2 | export const CREATE_MOTTO = 'CREATE_MOTTO';
3 | export const SET_IN_MOTTO = 'SET_IN_MOTTO';
4 | export const TOGGLE_MODAL = 'TOGGLE_MODAL';
5 |
--------------------------------------------------------------------------------
/Appendix04/graphql-example/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": {
3 | "id": "1",
4 | "name": "Dan"
5 | },
6 | "2": {
7 | "id": "2",
8 | "name": "Marie"
9 | },
10 | "3": {
11 | "id": "3",
12 | "name": "Jessie"
13 | }
14 | }
--------------------------------------------------------------------------------
/Ch04/README.md:
--------------------------------------------------------------------------------
1 | # Ch04 Props/State 基础与 Component 生命周期
2 |
3 | 1. [Props、State、Refs 与表单处理](props-state-introduction.md)
4 | 2. [React Component 规格与生命周期(Life Cycle)](react-component-life-cycle.md)
5 |
6 | ## :door: 任意门
7 | | [回首页](../../../tree/zh-CN/) |
--------------------------------------------------------------------------------
/Ch07/README.md:
--------------------------------------------------------------------------------
1 | # Ch07 Flux/Redux
2 |
3 | 1. [Flux 基础概念与实战入门](react-flux-introduction.md)
4 | 2. [Redux 基础概念](react-redux-introduction.md)
5 | 3. [Redux 实战入门](react-redux-real-world-example.md)
6 |
7 | ## :door: 任意门
8 | | [回首页](../../../tree/zh-CN/) |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
5 | },
6 | "env" :{
7 | "browser": true,
8 | "es6": true
9 | }
10 | }
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/NavLink/NavLink.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router';
3 |
4 | const NavLink = (props) => (
5 |
6 | );
7 |
8 | export default NavLink;
9 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/.eslint:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
5 | },
6 | "env" :{
7 | "browser": true,
8 | "es6": true
9 | }
10 | }
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux-immutable';
2 | import counterReducers from './counterReducers'
3 |
4 | const rootReducer = combineReducers({
5 | counterReducers
6 | });
7 |
8 | export default rootReducer;
9 |
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import Main from './components/Main';
4 |
5 | const App = () => (
6 |
7 | );
8 |
9 | ReactDOM.render(, document.getElementById('app'));
10 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/README.md:
--------------------------------------------------------------------------------
1 | # Redux
2 |
3 | # 延伸阅读
4 | 1. [Question: How to choose between Redux's store and React's state? #1287](https://github.com/reactjs/redux/issues/1287)
5 | 2. [What is the best approach to design state? #1825](https://github.com/reactjs/redux/issues/1825)
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
6 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Redux Todo
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/constants/models.js:
--------------------------------------------------------------------------------
1 | import Immutable from 'immutable';
2 |
3 | export const TodoState = Immutable.fromJS({
4 | 'todos': [],
5 | 'todo': {
6 | id: '',
7 | text: '',
8 | updatedAt: '',
9 | completed: false,
10 | }
11 | });
12 |
13 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/README.md:
--------------------------------------------------------------------------------
1 | # Redux
2 |
3 | # 延伸阅读
4 | 1. [Question: How to choose between Redux's store and React's state? #1287](https://github.com/reactjs/redux/issues/1287)
5 | 2. [What is the best approach to design state? #1825](https://github.com/reactjs/redux/issues/1825)
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/reducers/ui/uiReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import UiState from '../../constants/models';
3 |
4 | export default handleActions({
5 | SHOW: (state, { payload }) => (
6 | state.set('todos', payload.todo)
7 | ),
8 | }, UiState);
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/constants/models.js:
--------------------------------------------------------------------------------
1 | import Immutable from 'immutable';
2 |
3 | export const UiState = Immutable.fromJS({
4 | spinnerVisible: false,
5 | });
6 |
7 | export const GithubState = Immutable.fromJS({
8 | userId: '',
9 | data: {},
10 | });
11 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/src/components/Main/Main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Main = () => (
4 |
11 | );
12 |
13 | export default Main;
14 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Redux Todo
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/constants/models.js:
--------------------------------------------------------------------------------
1 | import Immutable from 'immutable';
2 |
3 | export const TodoState = Immutable.fromJS({
4 | 'todos': [],
5 | 'todo': {
6 | id: '',
7 | text: '',
8 | updatedAt: '',
9 | completed: false,
10 | }
11 | });
12 |
13 |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | TodoFlux
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/api/counter.js:
--------------------------------------------------------------------------------
1 | function getRandomInt(min, max) {
2 | return Math.floor(Math.random() * (max - min)) + min
3 | }
4 |
5 | export function fetchCounter(callback) {
6 | setTimeout(() => {
7 | callback(getRandomInt(1, 100))
8 | }, 500)
9 | }
10 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
6 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/reducers/ui/uiReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import UiState from '../../constants/models';
3 |
4 | export default handleActions({
5 | SHOW: (state, { payload }) => (
6 | state.set('todos', payload.todo)
7 | ),
8 | }, UiState);
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ReactRouter
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux-immutable';
2 | import ui from './ui/uiReducers';
3 | import motto from './data/mottoReducers';
4 |
5 | const rootReducer = combineReducers({
6 | ui,
7 | motto,
8 | });
9 |
10 | export default rootReducer;
11 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/containers/ResultPageContainer/ResultPageContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 | import ResultPage from '../../components/ResultPage';
3 |
4 | export default connect(
5 | state => ({
6 | data: state.getIn(['github', 'data']),
7 | })
8 | )(ResultPage);
9 |
--------------------------------------------------------------------------------
/Ch02/browserify-example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello React!
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/actions/uiActions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions';
2 | import {
3 | SHOW_SPINNER,
4 | HIDE_SPINNER,
5 | } from '../constants/actionTypes';
6 |
7 | export const showSpinner = createAction(SHOW_SPINNER);
8 | export const hideSpinner = createAction(HIDE_SPINNER);
9 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/MottoList/mottoStyles.js:
--------------------------------------------------------------------------------
1 | import { StyleSheet, Dimensions } from 'react-native';
2 | const { height } = Dimensions.get('window');
3 | export default StyleSheet.create({
4 | listView: {
5 | flex: 1,
6 | flexDirection: 'column',
7 | height: height - 105,
8 | },
9 | });
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/test/setup.js:
--------------------------------------------------------------------------------
1 | import jsdom from 'jsdom';
2 |
3 | if (typeof document === 'undefined') {
4 | global.document = jsdom.jsdom('');
5 | global.window = document.defaultView;
6 | global.navigator = global.window.navigator;
7 | }
8 |
--------------------------------------------------------------------------------
/Ch02/browserify-example/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello React!
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "HelloWorldApp",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "start": "node node_modules/react-native/local-cli/cli.js start"
7 | },
8 | "dependencies": {
9 | "react": "15.3.1",
10 | "react-native": "0.32.0"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/test/add.test.js:
--------------------------------------------------------------------------------
1 | // test add.js
2 | import add from '../src/modules/add';
3 | import { expect } from 'chai';
4 |
5 | // describe is test suite, it is test case
6 | describe('test add function', () => (
7 | it('1 + 1 = 2', () => (
8 | expect(add(1, 1)).to.be.equal(2)
9 | ))
10 | ));
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/Repos/Repos.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Repos = (props) => (
4 |
5 |
Repos
6 | {props.params.name}
7 |
8 | );
9 |
10 | Repos.propTypes = {
11 | params: React.PropTypes.Object,
12 | };
13 |
14 | export default Repos;
15 |
--------------------------------------------------------------------------------
/Ch02/webpack-example/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | React Setup
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Ch03/todo-examples/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | React Setup
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | GithubFinder
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/constants/models.js:
--------------------------------------------------------------------------------
1 | import Immutable from 'immutable';
2 |
3 | export const MottoState = Immutable.fromJS({
4 | mottos: [],
5 | motto: {
6 | id : '',
7 | text: '',
8 | updatedAt: '',
9 | }
10 | });
11 |
12 | export const UiState = Immutable.fromJS({
13 | isModalVisible: false,
14 | });
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux-immutable';
2 | import ui from './ui/uiReducers';// import routes from './routes';
3 | import todo from './data/todoReducers';// import routes from './routes';
4 |
5 | const rootReducer = combineReducers({
6 | todo,
7 | });
8 |
9 | export default rootReducer;
10 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import Main from './components/Main';
5 | import store from './store';
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById('app')
12 | );
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/actions/counterActions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions';
2 | import {
3 | INCREMENT_COUNT,
4 | DECREMENT_COUNT,
5 | } from '../constants/actionTypes';
6 |
7 | export const incrementCount = createAction(INCREMENT_COUNT);
8 | export const decrementCount = createAction(DECREMENT_COUNT);
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/Main/Main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AppBarContainer from '../../containers/AppBarContainer';
3 |
4 | const Main = (props) => (
5 |
6 |
7 |
8 | {props.children}
9 |
10 |
11 | );
12 |
13 | export default Main;
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/SharePageContainer/SharePageContainer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import SharePage from '../../components/SharePage';
4 |
5 | export default connect(
6 | (state) => ({
7 | }),
8 | (dispatch) => ({
9 | })
10 | )(SharePage);
11 |
12 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/utils/fetchComponentData.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | export default function fetchComponentData(token = 'token') {
4 | const promises = [axios.get('http://localhost:3000/api/recipes'), axios.get('http://localhost:3000/api/authenticate?token=' + token)];
5 | return Promise.all(promises);
6 | }
7 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/src/components/Main/Main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TodoHeader from '../TodoHeader';
3 | import TodoList from '../TodoList';
4 |
5 | const Main = (props) => (
6 |
7 |
Todos
8 |
9 |
10 |
11 | );
12 |
13 | export default Main;
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux-immutable';
2 | import ui from './ui/uiReducers';// import routes from './routes';
3 | import todo from './data/todoReducers';// import routes from './routes';
4 |
5 | const rootReducer = combineReducers({
6 | todo,
7 | });
8 |
9 | export default rootReducer;
10 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import Main from './components/Main';
5 | import store from './store';
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById('app')
12 | );
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/src/components/TodoList/TodoList.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const TodoList = (props) => (
4 |
5 |
6 | {
7 | props.todos.map((todo, index) => (
8 | - {todo.text}
9 | ))
10 | }
11 |
12 |
13 | );
14 |
15 | export default TodoList;
--------------------------------------------------------------------------------
/Ch07/react-flux-example/src/actions/todoActions.js:
--------------------------------------------------------------------------------
1 | import AppDispatcher from '../dispatcher/AppDispatcher';
2 | import { ADD_TODO } from '../constants/actionTypes';
3 |
4 | export const TodoActions = {
5 | addTodo(text) {
6 | AppDispatcher.handleAction({
7 | type: ADD_TODO,
8 | payload: {
9 | text,
10 | },
11 | });
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/constants/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const SHOW_SPINNER = 'SHOW_SPINNER';
2 | export const HIDE_SPINNER = 'HIDE_SPINNER';
3 | export const GET_GITHUB_INITIATE = 'GET_GITHUB_INITIATE';
4 | export const GET_GITHUB_SUCCESS = 'GET_GITHUB_SUCCESS';
5 | export const GET_GITHUB_FAIL = 'GET_GITHUB_FAIL';
6 | export const CHAGE_USER_ID = 'CHAGE_USER_ID';
7 |
--------------------------------------------------------------------------------
/Ch10/README.md:
--------------------------------------------------------------------------------
1 | # Ch10 实战教学:用 React + Redux + Node(Isomorphic JavaScript)开发食谱分享网站
2 |
3 | 1. [React Redux Sever Rendering(Isomorphic JavaScript)入门](react-redux-server-rendering-isomorphic-javascript.md)
4 | 2. [用 React + Redux + Node(Isomorphic JavaScript)开发一个食谱分享网站](react-router-redux-node-isomorphic-javascript-open-cook.md)
5 |
6 | ## :door: 任意门
7 | | [回首页](../../../tree/zh-CN/) |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux-immutable';
2 | import ui from './ui/uiReducers';// import routes from './routes';
3 | import github from './data/githubReducers';// import routes from './routes';
4 |
5 | const rootReducer = combineReducers({
6 | ui,
7 | github,
8 | });
9 |
10 | export default rootReducer;
11 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/actions/todoActions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions';
2 | import {
3 | CREATE_TODO,
4 | DELETE_TODO,
5 | CHANGE_TEXT,
6 | } from '../constants/actionTypes';
7 |
8 | export const createTodo = createAction('CREATE_TODO');
9 | export const deleteTodo = createAction('DELETE_TODO');
10 | export const changeText = createAction('CHANGE_TEXT');
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/test/promise.test.js:
--------------------------------------------------------------------------------
1 | import fetch from 'node-fetch';
2 | import { expect } from 'chai';
3 |
4 | it('asynchronous fetch promise', function() {
5 | return fetch('https://api.github.com/users/torvus')
6 | .then(function(response) { return response.json() })
7 | .then(function(json) {
8 | expect(json).to.be.an('object');
9 | });
10 | });
--------------------------------------------------------------------------------
/Ch03/todo-examples/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | React Setup
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/ListItem/listItemStyles.js:
--------------------------------------------------------------------------------
1 | import { StyleSheet } from 'react-native';
2 |
3 | export default StyleSheet.create({
4 | listItemContainer: {
5 | flex: 1,
6 | flexDirection: 'row',
7 | padding: 10,
8 | margin: 5,
9 | },
10 | listItemText: {
11 | flex: 10,
12 | fontSize: 18,
13 | color: '#212121',
14 | }
15 | });
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/actions/todoActions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions';
2 | import {
3 | CREATE_TODO,
4 | DELETE_TODO,
5 | CHANGE_TEXT,
6 | } from '../constants/actionTypes';
7 |
8 | export const createTodo = createAction('CREATE_TODO');
9 | export const deleteTodo = createAction('DELETE_TODO');
10 | export const changeText = createAction('CHANGE_TEXT');
--------------------------------------------------------------------------------
/Ch02/webpack-example/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | React Setup
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | OpenWeather
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/actions/mottoActions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions';
2 | import {
3 | GET_MOTTOS,
4 | CREATE_MOTTO,
5 | SET_IN_MOTTO,
6 | } from '../constants/actionTypes';
7 |
8 | export const getMottos = createAction('GET_MOTTOS');
9 | export const createMotto = createAction('CREATE_MOTTO');
10 | export const setInMotto = createAction('SET_IN_MOTTO');
11 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/HomePageContainer/HomePageContainer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import HomePage from '../../components/HomePage';
4 |
5 | export default connect(
6 | (state) => ({
7 | recipes: state.getIn(['recipe', 'recipes']),
8 | }),
9 | (dispatch) => ({
10 | })
11 | )(HomePage);
12 |
13 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/ToolBar/ToolBar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactNative from 'react-native';
3 | import styles from './toolBarStyles';
4 | const { View, Text } = ReactNative;
5 |
6 | const ToolBar = () => (
7 |
8 | Startup Mottos
9 |
10 | );
11 |
12 | export default ToolBar;
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/components/Main/Main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import TodoHeaderContainer from '../../containers/TodoHeaderContainer';
4 | import TodoListContainer from '../../containers/TodoListContainer';
5 |
6 | const Main = () => (
7 |
8 |
9 |
10 |
11 | );
12 |
13 | export default Main;
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/LoginPageContainer/LoginPageContainer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import LoginPage from '../../components/LoginPage';
4 |
5 | export default connect(
6 | (state) => ({
7 | spinnerVisible: state.getIn(['ui', 'spinnerVisible']),
8 | }),
9 | (dispatch) => ({
10 | })
11 | )(LoginPage);
12 |
13 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/components/Main/Main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import TodoHeaderContainer from '../../containers/TodoHeaderContainer';
4 | import TodoListContainer from '../../containers/TodoListContainer';
5 |
6 | const Main = () => (
7 |
8 |
9 |
10 |
11 | );
12 |
13 | export default Main;
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
5 | "import/no-extraneous-dependencies": [0],
6 | "linebreak-style": ["error", "unix"],
7 | "react/prop-types": ["error", {"ignore": ["children", "route"]}],
8 | "new-cap": [0],
9 | },
10 | "env" :{
11 | "browser": true,
12 | }
13 | }
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux-immutable';
2 | import ui from './ui/uiReducers';
3 | import recipe from './data/recipeReducers';
4 | import user from './data/userReducers';
5 | // import routes from './routes';
6 |
7 | const rootReducer = combineReducers({
8 | ui,
9 | recipe,
10 | user,
11 | });
12 |
13 | export default rootReducer;
14 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/ToolBar/toolBarStyles.js:
--------------------------------------------------------------------------------
1 | import { StyleSheet } from 'react-native';
2 |
3 | export default StyleSheet.create({
4 | toolBarContainer: {
5 | height: 40,
6 | justifyContent: 'center',
7 | alignItems: 'center',
8 | flexDirection: 'column',
9 | backgroundColor: '#ffeb3b',
10 | },
11 | toolBarText: {
12 | fontSize: 20,
13 | color: '#212121'
14 | }
15 | });
--------------------------------------------------------------------------------
/Appendix04/graphql-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "graphql-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "kdchang",
10 | "license": "MIT",
11 | "dependencies": {
12 | "express": "^4.14.0",
13 | "express-graphql": "^0.5.4",
14 | "graphql": "^0.7.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/test/async.test.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import { expect } from 'chai';
3 |
4 | it('asynchronous return an object', function(done){
5 | axios
6 | .get('https://api.github.com/users/torvus')
7 | .then(function (response) {
8 | expect(response).to.be.an('object');
9 | done();
10 | })
11 | .catch(function (error) {
12 | console.log(error);
13 | });
14 | });
--------------------------------------------------------------------------------
/Ch02/webpack-example/app/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | class App extends React.Component {
5 | constructor(props) {
6 | super(props);
7 | this.state = {
8 | };
9 | }
10 | render() {
11 | return (
12 |
13 |
Hello, World!
14 |
15 | );
16 | }
17 | }
18 |
19 | ReactDOM.render(, document.getElementById('app'));
20 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/ActionButton/actionButtonStyles.js:
--------------------------------------------------------------------------------
1 | import { StyleSheet } from 'react-native';
2 |
3 | export default StyleSheet.create({
4 | buttonContainer: {
5 | height: 40,
6 | justifyContent: 'center',
7 | alignItems: 'center',
8 | flexDirection: 'column',
9 | backgroundColor: '#66bb6a',
10 | },
11 | buttonText: {
12 | fontSize: 20,
13 | color: '#e8f5e9'
14 | }
15 | });
--------------------------------------------------------------------------------
/Ch02/browserify-example/app/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | class App extends React.Component {
5 | constructor(props) {
6 | super(props);
7 | this.state = {
8 | };
9 | }
10 | render() {
11 | return (
12 |
13 |
Hello, World!
14 |
15 | );
16 | }
17 | }
18 |
19 | ReactDOM.render(, document.getElementById('app'));
20 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/containers/ActionButtonContainer/ActionButtonContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 | import ActionButton from '../../components/ActionButton';
3 | import {
4 | toggleModal,
5 | } from '../../actions';
6 |
7 | export default connect(
8 | (state) => ({}),
9 | (dispatch) => ({
10 | onToggleModal: () => (
11 | dispatch(toggleModal())
12 | )
13 | })
14 | )(ActionButton);
15 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/store/configureStore.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware } from 'redux';
2 | import createLogger from 'redux-logger';
3 | import Immutable from 'immutable';
4 | import rootReducer from '../reducers';
5 |
6 | const initialState = Immutable.Map();
7 |
8 | export default createStore(
9 | rootReducer,
10 | initialState,
11 | applyMiddleware(createLogger({ stateTransformer: state => state.toJS() }))
12 | );
13 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/components/TodoHeader/TodoHeader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | const TodoHeader = ({
5 | onChangeText,
6 | onCreateTodo,
7 | todo,
8 | }) => (
9 |
10 |
TodoHeader
11 |
12 |
13 |
14 | );
15 |
16 | export default TodoHeader;
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/actions/uiActions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions';
2 | import WebAPI from '../utils/WebAPI';
3 |
4 | import {
5 | SHOW_SPINNER,
6 | HIDE_SPINNER,
7 | SET_UI,
8 | } from '../constants/actionTypes';
9 |
10 | export const showSpinner = createAction('SHOW_SPINNER');
11 | export const hideSpinner = createAction('HIDE_SPINNER');
12 | export const setUi = createAction('SET_UI');
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/store/configureStore.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware } from 'redux';
2 | import createLogger from 'redux-logger';
3 | import Immutable from 'immutable';
4 | import rootReducer from '../reducers';
5 |
6 | const initialState = Immutable.Map();
7 |
8 | export default createStore(
9 | rootReducer,
10 | initialState,
11 | applyMiddleware(createLogger({ stateTransformer: state => state.toJS() }))
12 | );
13 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/store/configureStore.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware } from 'redux';
2 | import createLogger from 'redux-logger';
3 | import Immutable from 'immutable';
4 | import rootReducer from '../reducers';
5 |
6 | const initialState = Immutable.Map();
7 |
8 | export default createStore(
9 | rootReducer,
10 | initialState,
11 | applyMiddleware(createLogger({ stateTransformer: state => state.toJS() }))
12 | );
13 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/components/TodoHeader/TodoHeader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | const TodoHeader = ({
5 | onChangeText,
6 | onCreateTodo,
7 | todo,
8 | }) => (
9 |
10 |
TodoHeader
11 |
12 |
13 |
14 | );
15 |
16 | export default TodoHeader;
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/HomePage/HomePage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import RecipeBoxContainer from '../../containers/RecipeBoxContainer';
3 |
4 | const HomePage = ({
5 | recipes
6 | }) => (
7 |
8 | {
9 | recipes.map((recipe, index) => (
10 |
11 | )).toJS()
12 | }
13 |
14 | );
15 |
16 | export default HomePage;
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/components/ResultPage/ResultPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import GithubBox from '../../components/GithubBox';
3 |
4 | const ResultPage = props => (
5 |
6 |
7 |
8 | );
9 |
10 | ResultPage.propTypes = {
11 | data: React.PropTypes.string,
12 | location: React.PropTypes.Object,
13 | };
14 |
15 | export default ResultPage;
16 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/components/Main/Main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AppBar from 'material-ui/AppBar';
3 |
4 | const Main = props => (
5 |
6 |
10 |
11 | {props.children}
12 |
13 |
14 | );
15 |
16 | Main.propTypes = {
17 | children: React.PropTypes.Object,
18 | };
19 |
20 | export default Main;
21 |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/src/dispatcher/AppDispatcher.js:
--------------------------------------------------------------------------------
1 | // Todo app dispatcher with actions responding to both
2 | // view and server actions
3 | import { Dispatcher } from 'flux';
4 |
5 | class DispatcherClass extends Dispatcher {
6 |
7 | handleAction(action) {
8 | this.dispatch({
9 | type: action.type,
10 | payload: action.payload,
11 | });
12 | }
13 |
14 | }
15 |
16 | const AppDispatcher = new DispatcherClass();
17 |
18 | export default AppDispatcher;
19 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/containers/TodoListContainer/TodoListContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 | import TodoList from '../../components/TodoList';
3 |
4 | import {
5 | deleteTodo,
6 | } from '../../actions';
7 |
8 | export default connect(
9 | (state) => ({
10 | todos: state.getIn(['todo', 'todos'])
11 | }),
12 | (dispatch) => ({
13 | onDeleteTodo: (index) => () => (
14 | dispatch(deleteTodo({ index }))
15 | )
16 | })
17 | )(TodoList);
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/SharePage/SharePage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Grid, Row, Col } from 'react-bootstrap';
3 | import ShareBoxContainer from '../../containers/ShareBoxContainer';
4 |
5 | const SharePage = () => (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | );
14 |
15 | export default SharePage;
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/test/enzyme/shallowRender.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TestUtils from 'react-addons-test-utils';
3 | import { expect } from 'chai';
4 | import { shallow } from 'enzyme';
5 | import Main from '../../src/components/Main';
6 |
7 | describe('Enzyme Shallow Rendering', () => {
8 | it('Main title should be Todos', () => {
9 | const main = shallow();
10 | expect(main.find('h1').text()).to.equal('Todos');
11 | });
12 | });
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/reducers/ui/uiReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import {
3 | UiState,
4 | } from '../../constants/models';
5 |
6 | import {
7 | TOGGLE_MODAL,
8 | } from '../../constants/actionTypes';
9 |
10 | const uiReducers = handleActions({
11 | TOGGLE_MODAL: (state) => (
12 | state.set(
13 | 'isModalVisible',
14 | !state.get('isModalVisible')
15 | )
16 | ),
17 | }, UiState);
18 |
19 | export default uiReducers;
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/containers/TodoListContainer/TodoListContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 | import TodoList from '../../components/TodoList';
3 |
4 | import {
5 | deleteTodo,
6 | } from '../../actions';
7 |
8 | export default connect(
9 | (state) => ({
10 | todos: state.getIn(['todo', 'todos'])
11 | }),
12 | (dispatch) => ({
13 | onDeleteTodo: (index) => () => (
14 | dispatch(deleteTodo({ index }))
15 | )
16 | })
17 | )(TodoList);
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/reducers/ui/uiReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import { UiState } from '../../constants/models';
3 |
4 | const uiReducers = handleActions({
5 | SHOW_SPINNER: state => (
6 | state.set(
7 | 'spinnerVisible',
8 | true
9 | )
10 | ),
11 | HIDE_SPINNER: state => (
12 | state.set(
13 | 'spinnerVisible',
14 | false
15 | )
16 | ),
17 | }, UiState);
18 |
19 | export default uiReducers;
20 |
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/README.md:
--------------------------------------------------------------------------------
1 | # Redux Server 端 Rendering
2 |
3 | 要把资料从伺服器端传递到客户端,我们需要:
4 |
5 | 1. 对每个请求建立一个全新的 Redux store 实体
6 | 2. 选择性的 dispatch 一些 action
7 | 3. 把 state 从 store 取出来
8 | 4. 把 state 一起传到客户端
9 |
10 | # 延伸阅读
11 | 1. [Immutable.js usage - Reducers & Server Side Rendering](https://github.com/reactjs/redux/issues/1555)
12 | 2. [Redux Server Rendering](http://redux.js.org/docs/recipes/ServerRendering.html)
13 | 3. [React Router Tutorial](https://github.com/reactjs/react-router-tutorial)
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/server/models/user.js:
--------------------------------------------------------------------------------
1 | // get an instance of mongoose and mongoose.Schema
2 | // const mongoose = require('mongoose');
3 | // const Schema = mongoose.Schema;
4 | import mongoose, { Schema } from 'mongoose';
5 |
6 | // set up a mongoose model and pass it using module.exports
7 | export default mongoose.model('User', new Schema({
8 | id: Number,
9 | username: String,
10 | email: String,
11 | password: String,
12 | admin: Boolean
13 | }));
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/app/src/main/java/com/helloworldapp/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.helloworldapp;
2 |
3 | import com.facebook.react.ReactActivity;
4 |
5 | public class MainActivity extends ReactActivity {
6 |
7 | /**
8 | * Returns the name of the main component registered from JavaScript.
9 | * This is used to schedule rendering of the component.
10 | */
11 | @Override
12 | protected String getMainComponentName() {
13 | return "HelloWorldApp";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/store/configureStore.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware } from 'redux';
2 | import reduxThunk from 'redux-thunk';
3 | import createLogger from 'redux-logger';
4 | import Immutable from 'immutable';
5 | import rootReducer from '../reducers';
6 |
7 | const initialState = Immutable.Map();
8 |
9 | export default createStore(
10 | rootReducer,
11 | initialState,
12 | applyMiddleware(reduxThunk, createLogger({ stateTransformer: state => state.toJS() }))
13 | );
14 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/components/TodoList/TodoList.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | const TodoList = ({
5 | todos,
6 | onDeleteTodo,
7 | }) => (
8 |
9 |
10 | {
11 | todos.map((todo, index) => (
12 | -
13 | {todo.get('text')}
14 |
15 |
16 | )).toJS()
17 | }
18 |
19 |
20 | );
21 |
22 | export default TodoList;
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/components/TodoList/TodoList.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | const TodoList = ({
5 | todos,
6 | onDeleteTodo,
7 | }) => (
8 |
9 |
10 | {
11 | todos.map((todo, index) => (
12 | -
13 | {todo.get('text')}
14 |
15 |
16 | )).toJS()
17 | }
18 |
19 |
20 | );
21 |
22 | export default TodoList;
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/server/models/recipe.js:
--------------------------------------------------------------------------------
1 | // get an instance of mongoose and mongoose.Schema
2 | // const mongoose = require('mongoose');
3 | // const Schema = mongoose.Schema;
4 |
5 | import mongoose, { Schema } from 'mongoose';
6 |
7 | // set up a mongoose model and pass it using module.exports
8 | export default mongoose.model('Recipe', new Schema({
9 | id: String,
10 | name: String,
11 | description: String,
12 | imagePath: String,
13 | steps: Array,
14 | updatedAt: Date,
15 | }));
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/reducers/data/githubReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import { GithubState } from '../../constants/models';
3 |
4 | const githubReducers = handleActions({
5 | GET_GITHUB_SUCCESS: (state, { payload }) => (
6 | state.merge({
7 | data: payload.data,
8 | })
9 | ),
10 | CHAGE_USER_ID: (state, { payload }) => (
11 | state.merge({
12 | userId:
13 | payload.userId,
14 | })
15 | ),
16 | }, GithubState);
17 |
18 | export default githubReducers;
19 |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import TodoHeader from './components/TodoHeader';
4 | import TodoList from './components/TodoList';
5 |
6 | class App extends React.Component {
7 | constructor(props) {
8 | super(props);
9 | this.state = {};
10 | }
11 | render() {
12 | return (
13 |
14 |
15 |
16 |
17 | );
18 | }
19 | }
20 |
21 | ReactDOM.render(, document.getElementById('app'));
22 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/java/com/reactnativefirebasemotto/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.reactnativefirebasemotto;
2 |
3 | import com.facebook.react.ReactActivity;
4 |
5 | public class MainActivity extends ReactActivity {
6 |
7 | /**
8 | * Returns the name of the main component registered from JavaScript.
9 | * This is used to schedule rendering of the component.
10 | */
11 | @Override
12 | protected String getMainComponentName() {
13 | return "ReactNativeFirebaseMotto";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/ios/HelloWorldApp/AppDelegate.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | @interface AppDelegate : UIResponder
13 |
14 | @property (nonatomic, strong) UIWindow *window;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/Ch03/todo-examples/app/components/TodoList/TodoList.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 |
3 | const TodoList = (props) => (
4 |
5 |
TodoList
6 |
7 | {
8 | props.todos.map((todo, index) => (
9 | -
10 |
{todo.title}
11 |
12 | ))
13 | }
14 |
15 |
16 | );
17 |
18 | TodoList.propTypes = {
19 | todos: PropTypes.array,
20 | };
21 |
22 | TodoList.defaultProps = {
23 | todos: [],
24 | };
25 |
26 | export default TodoList;
27 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/ActionButton/ActionButton.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactNative from 'react-native';
3 | import styles from './actionButtonStyles';
4 | const { View, Text, Modal, TextInput, TouchableHighlight } = ReactNative;
5 |
6 | const ActionButton = (props) => (
7 |
8 |
9 | Add Motto
10 |
11 |
12 | );
13 |
14 | export default ActionButton;
15 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/test/enzyme/staticRender.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TestUtils from 'react-addons-test-utils';
3 | import { expect } from 'chai';
4 | import { render } from 'enzyme';
5 | import Main from '../../src/components/Main';
6 |
7 | describe('Enzyme Staic Rendering', () => {
8 | it('Main title should be Todos', () => {
9 | const todos = [{ id: 0, text: 'reading'}, { id: 1, text: 'coding'}];
10 | const main = render();
11 | expect(main.find('h1').text()).to.equal('Todos');
12 | });
13 | });
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/index.android.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | * @flow
5 | */
6 |
7 | import React, { Component } from 'react';
8 | import {
9 | AppRegistry,
10 | Text,
11 | View
12 | } from 'react-native';
13 | import Main from './src/components/Main';
14 |
15 | class ReactNativeFirebaseMotto extends Component {
16 | render() {
17 | return (
18 |
19 | );
20 | }
21 | }
22 |
23 | AppRegistry.registerComponent('ReactNativeFirebaseMotto', () => ReactNativeFirebaseMotto);
24 |
--------------------------------------------------------------------------------
/Ch03/todo-examples/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | 'extends': 'airbnb',
3 | 'parser': 'babel-eslint',
4 | 'plugins': [
5 | 'react',
6 | ],
7 | "parserOptions": {
8 | "ecmaFeatures": {
9 | "jsx": true,
10 | "modules": true,
11 | }
12 | },
13 | 'rules': {
14 | 'react/prefer-es6-class': 1,
15 | 'react/jsx-pascal-case': 1,
16 | 'react/jsx-closing-bracket-location': 1,
17 | 'react/wrap-multilines': 1,
18 | 'react/self-closing-comp': 1,
19 | 'react/sort-comp': 1,
20 | 'global-require': 0,
21 | },
22 | };
23 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/ios/ReactNativeFirebaseMotto/AppDelegate.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | @interface AppDelegate : UIResponder
13 |
14 | @property (nonatomic, strong) UIWindow *window;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/index.ios.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | * @flow
5 | */
6 |
7 | import React, { Component } from 'react';
8 | import {
9 | AppRegistry,
10 | StyleSheet,
11 | Text,
12 | View
13 | } from 'react-native';
14 | import Main from './src/components/Main';
15 |
16 | class ReactNativeFirebaseMotto extends Component {
17 | render() {
18 | return (
19 |
20 | );
21 | }
22 | }
23 |
24 | AppRegistry.registerComponent('ReactNativeFirebaseMotto', () => ReactNativeFirebaseMotto);
25 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/constants/models.js:
--------------------------------------------------------------------------------
1 | import Immutable from 'immutable';
2 |
3 | // initstate model
4 | export const UiState = Immutable.fromJS({
5 | spinnerVisible: false,
6 | isEdit: false,
7 | });
8 |
9 | export const RecipeState = Immutable.fromJS({
10 | recipes: [],
11 | recipe: {
12 | id: '',
13 | name: '',
14 | description: '',
15 | imagePath: '',
16 | }
17 | });
18 |
19 | export const UserState = Immutable.fromJS({
20 | username: '',
21 | email: '',
22 | password: '',
23 | isAuthorized: false,
24 | });
25 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/test/enzyme/mount.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TestUtils from 'react-addons-test-utils';
3 | import { expect } from 'chai';
4 | import { findDOMNode } from 'react-dom';
5 | import { mount } from 'enzyme';
6 | import TodoHeader from '../../src/components/TodoHeader';
7 |
8 | describe('Enzyme Mount', () => {
9 | it('Click Button', () => {
10 | let todoHeaderDOM = mount();
11 | let button = todoHeaderDOM.find('button').at(0);
12 | button.simulate('click');
13 | expect(button.prop('disabled')).to.equal(true);
14 | });
15 | });
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/containers/CounterContainer/CounterContainer.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill';
2 | import { connect } from 'react-redux';
3 | import Counter from '../../components/Counter';
4 |
5 | import {
6 | incrementCount,
7 | decrementCount,
8 | } from '../../actions';
9 |
10 | export default connect(
11 | (state) => ({
12 | count: state.get('counterReducers').get('count'),
13 | }),
14 | (dispatch) => ({
15 | onIncrement: () => (
16 | dispatch(incrementCount())
17 | ),
18 | onDecrement: () => (
19 | dispatch(decrementCount())
20 | ),
21 | })
22 | )(Counter);
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/ios/HelloWorldApp/main.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | #import "AppDelegate.h"
13 |
14 | int main(int argc, char * argv[]) {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 | # Android/IJ
26 | #
27 | *.iml
28 | .idea
29 | .gradle
30 | local.properties
31 |
32 | # node.js
33 | #
34 | node_modules/
35 | npm-debug.log
36 |
37 | # BUCK
38 | buck-out/
39 | \.buckd/
40 | android/app/libs
41 | android/keystores/debug.keystore
42 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/ListItem/ListItem.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactNative from 'react-native';
3 | import styles from './listItemStyles';
4 | const { View, Text, TouchableHighlight } = ReactNative;
5 |
6 | const ListItem = (props) => {
7 | return (
8 |
9 | {props.item.get('text')}
10 |
11 | Delete
12 |
13 |
14 | )
15 | };
16 |
17 | export default ListItem;
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/reducers/data/recipeReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import { RecipeState } from '../../constants/models';
3 |
4 | import {
5 | GET_RECIPES,
6 | SET_RECIPE,
7 | } from '../../constants/actionTypes';
8 |
9 | const recipeReducers = handleActions({
10 | GET_RECIPES: (state, { payload }) => (
11 | state.set(
12 | 'recipes',
13 | payload.recipes
14 | )
15 | ),
16 | SET_RECIPE: (state, { payload }) => (
17 | state.setIn(payload.keyPath, payload.value)
18 | ),
19 | }, RecipeState);
20 |
21 | export default recipeReducers;
22 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/ios/ReactNativeFirebaseMotto/main.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | #import "AppDelegate.h"
13 |
14 | int main(int argc, char * argv[]) {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Ch03/todo-examples/gulpfile.js:
--------------------------------------------------------------------------------
1 | require('babel-core/register');
2 |
3 | const gulp = require('gulp');
4 | const eslint = require('gulp-eslint');
5 | const gulpIf = require('gulp-if');
6 |
7 | const fix = false;
8 |
9 | function isFixed(file) {
10 | return file.eslint !== null && file.eslint.fixed;
11 | }
12 |
13 | gulp.task('eslint', () =>
14 | gulp.src([
15 | 'app/index.*.js',
16 | 'app/*.js',
17 | 'app/**/*.js',
18 | 'app/**/**/*.js',
19 | 'app/**/**/**/*.js',
20 | ])
21 | .pipe(eslint({ fix }))
22 | .pipe(eslint.format())
23 | .pipe(eslint.failAfterError())
24 | .pipe(gulpIf(isFixed, gulp.dest('src')))
25 | );
26 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/containers/TodoHeaderContainer/TodoHeaderContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 | import TodoHeader from '../../components/TodoHeader';
3 |
4 | import {
5 | changeText,
6 | createTodo,
7 | } from '../../actions';
8 |
9 | export default connect(
10 | (state) => ({
11 | todo: state.getIn(['todo', 'todo'])
12 | }),
13 | (dispatch) => ({
14 | onChangeText: (event) => (
15 | dispatch(changeText({ text: event.target.value }))
16 | ),
17 | onCreateTodo: () => {
18 | dispatch(createTodo());
19 | dispatch(changeText({ text: '' }));
20 | }
21 | })
22 | )(TodoHeader);
23 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 | # Android/IJ
26 | #
27 | *.iml
28 | .idea
29 | .gradle
30 | local.properties
31 |
32 | # node.js
33 | #
34 | node_modules/
35 | npm-debug.log
36 |
37 | # BUCK
38 | buck-out/
39 | \.buckd/
40 | android/app/libs
41 | android/keystores/debug.keystore
42 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/LoginPage/LoginPage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Grid, Row, Col, Image } from 'react-bootstrap';
3 | import LoginBoxContainer from '../../containers/LoginBoxContainer';
4 |
5 | const LoginPage = ({
6 | spinnerVisible,
7 | }) => (
8 |
9 |
10 |
11 |
12 | { spinnerVisible === true ?
13 | :
14 | null
15 | }
16 |
17 |
18 |
19 | );
20 |
21 | export default LoginPage;
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/containers/TodoHeaderContainer/TodoHeaderContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 | import TodoHeader from '../../components/TodoHeader';
3 |
4 | import {
5 | changeText,
6 | createTodo,
7 | } from '../../actions';
8 |
9 | export default connect(
10 | (state) => ({
11 | todo: state.getIn(['todo', 'todo'])
12 | }),
13 | (dispatch) => ({
14 | onChangeText: (event) => (
15 | dispatch(changeText({ text: event.target.value }))
16 | ),
17 | onCreateTodo: () => {
18 | dispatch(createTodo());
19 | dispatch(changeText({ text: '' }));
20 | }
21 | })
22 | )(TodoHeader);
23 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | 'react/prefer-es6-class': 1,
5 | 'react/jsx-pascal-case': 1,
6 | 'react/jsx-closing-bracket-location': 1,
7 | 'react/jsx-filename-extension': [1, { "extensions": [".js", ".jsx"] }],
8 | 'import/extensions': 1,
9 | 'import/no-extraneous-dependencies': 1,
10 | 'react/self-closing-comp': 1,
11 | 'react/jsx-wrap-multilines': 1,
12 | 'react/sort-comp': 1,
13 | 'no-undef': 1,
14 | 'no-unused-vars': 1,
15 | 'no-underscore-dangle': 1,
16 | 'global-require': 0,
17 | 'import/prefer-default-export': 1,
18 | 'new-cap': 1,
19 | }
20 | }
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/store/configureStore.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware } from 'redux';
2 | import promiseMiddleware from 'redux-promise';
3 | import createLogger from 'redux-logger';
4 | import Immutable from 'immutable';
5 | import rootReducer from '../reducers';
6 |
7 | const initialState = Immutable.Map();
8 |
9 | export default function configureStore(preloadedState = initialState) {
10 | const store = createStore(
11 | rootReducer,
12 | preloadedState,
13 | applyMiddleware(createLogger({ stateTransformer: state => state.toJS() }, promiseMiddleware))
14 | );
15 |
16 | return store;
17 | }
18 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/src/components/TodoHeader/TodoHeader.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | class TodoHeader extends React.Component {
4 | constructor(props) {
5 | super(props);
6 | this.toggleButton = this.toggleButton.bind(this);
7 | this.state = {
8 | isActivated: false,
9 | };
10 | }
11 | toggleButton() {
12 | this.setState({
13 | isActivated: !this.state.isActivated,
14 | })
15 | }
16 | render() {
17 | return (
18 |
19 |
20 |
21 | );
22 | };
23 | }
24 |
25 | export default TodoHeader;
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/reducers/counterReducers.js:
--------------------------------------------------------------------------------
1 | import { fromJS } from 'immutable';
2 | import { handleActions } from 'redux-actions';
3 | import { CounterState } from '../constants/models';
4 |
5 | import {
6 | INCREMENT_COUNT,
7 | DECREMENT_COUNT,
8 | } from '../constants/actionTypes';
9 |
10 | const counterReducers = handleActions({
11 | INCREMENT_COUNT: (state) => (
12 | state.set(
13 | 'count',
14 | state.get('count') + 1
15 | )
16 | ),
17 | DECREMENT_COUNT: (state) => (
18 | state.set(
19 | 'count',
20 | state.get('count') - 1
21 | )
22 | ),
23 | }, CounterState);
24 |
25 | export default counterReducers;
26 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/test/shallowRender.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TestUtils from 'react-addons-test-utils';
3 | import { expect } from 'chai';
4 | import Main from '../src/components/Main';
5 |
6 | const shallowRender = (Component) => {
7 | const renderer = TestUtils.createRenderer();
8 | renderer.render();
9 | return renderer.getRenderOutput();
10 | }
11 |
12 | describe('Shallow Rendering', () => {
13 | it('Main title should be h1', () => {
14 | const todoItem = shallowRender(Main);
15 | expect(todoItem.props.children[0].type).to.equal('h1');
16 | expect(todoItem.props.children[0].props.children).to.equal('Todos');
17 | });
18 | });
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/actions/recipeActions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions';
2 | import WebAPI from '../utils/WebAPI';
3 |
4 | import {
5 | GET_RECIPES,
6 | ADD_RECIPE,
7 | UPDATE_RECIPE,
8 | DELETE_RECIPE,
9 | SET_RECIPE,
10 | } from '../constants/actionTypes';
11 |
12 | export const getRecipes = createAction('GET_RECIPES', WebAPI.getRecipes);
13 | export const addRecipe = createAction('ADD_RECIPE', WebAPI.addRecipe);
14 | export const updateRecipe = createAction('UPDATE_RECIPE', WebAPI.updateRecipe);
15 | export const deleteRecipe = createAction('DELETE_RECIPE', WebAPI.deleteRecipe);
16 | export const setRecipe = createAction('SET_RECIPE');
17 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/actions/userActions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions';
2 | import WebAPI from '../utils/WebAPI';
3 |
4 | import {
5 | AUTH_START,
6 | AUTH_COMPLETE,
7 | AUTH_ERROR,
8 | START_LOGOUT,
9 | CHECK_AUTH,
10 | SET_USER
11 | } from '../constants/actionTypes';
12 |
13 | export const authStart = createAction('AUTH_START', WebAPI.login);
14 | export const authComplete = createAction('AUTH_COMPLETE');
15 | export const authError = createAction('AUTH_ERROR');
16 | export const startLogout = createAction('START_LOGOUT', WebAPI.logout);
17 | export const checkAuth = createAction('CHECK_AUTH');
18 | export const setUser = createAction('SET_USER');
19 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/constants/actionTypes.js:
--------------------------------------------------------------------------------
1 | export const AUTH_START = "AUTH_START";
2 | export const AUTH_COMPLETE = "AUTH_COMPLETE";
3 | export const AUTH_ERROR = "AUTH_ERROR";
4 | export const START_LOGOUT = "START_LOGOUT";
5 | export const CHECK_AUTH = "CHECK_AUTH";
6 | export const SET_USER = "SET_USER";
7 | export const SHOW_SPINNER = "SHOW_SPINNER";
8 | export const HIDE_SPINNER = "HIDE_SPINNER";
9 | export const SET_UI = "SET_UI";
10 | export const GET_RECIPES = 'GET_RECIPES';
11 | export const SET_RECIPE = 'SET_RECIPE';
12 | export const ADD_RECIPE = 'ADD_RECIPE';
13 | export const UPDATE_RECIPE = 'UPDATE_RECIPE';
14 | export const DELETE_RECIPE = 'DELETE_RECIPE';
15 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/reducers/ui/uiReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import { UiState } from '../../constants/models';
3 |
4 | import {
5 | SHOW_SPINNER,
6 | HIDE_SPINNER,
7 | SET_UI,
8 | } from '../../constants/actionTypes';
9 |
10 | const uiReducers = handleActions({
11 | SHOW_SPINNER: (state) => (
12 | state.set(
13 | 'spinnerVisible',
14 | true
15 | )
16 | ),
17 | HIDE_SPINNER: (state) => (
18 | state.set(
19 | 'spinnerVisible',
20 | false
21 | )
22 | ),
23 | SET_UI: (state, { payload }) => (
24 | state.set(payload.key, payload.value)
25 | ),
26 | }, UiState);
27 |
28 | export default uiReducers;
29 |
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/client/index.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill';
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import { Provider } from 'react-redux';
5 | import CounterContainer from '../common/containers/CounterContainer';
6 | import configureStore from '../common/store/configureStore'
7 | import { fromJS } from 'immutable';
8 |
9 | // get initial state from server side
10 | const initialState = window.__PRELOADED_STATE__;
11 |
12 | // use initial state to create store and pass to provider
13 | const store = configureStore(fromJS(initialState))
14 |
15 | ReactDOM.render(
16 |
17 |
18 | ,
19 | document.getElementById('app')
20 | );
21 |
22 |
--------------------------------------------------------------------------------
/Ch03/todo-examples/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin');
2 |
3 | const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
4 | template: `${__dirname}/app/index.html`,
5 | filename: 'index.html',
6 | inject: 'body',
7 | });
8 |
9 | module.exports = {
10 | entry: [
11 | './app/index.js',
12 | ],
13 | output: {
14 | path: `${__dirname}/dist`,
15 | filename: 'index_bundle.js',
16 | },
17 | module: {
18 | loaders: [
19 | {
20 | test: /\.js$/,
21 | exclude: /node_modules/,
22 | loader: 'babel-loader',
23 | },
24 | ],
25 | },
26 | devServer: {
27 | inline: true,
28 | port: 8008,
29 | },
30 | plugins: [HTMLWebpackPluginConfig],
31 | };
32 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/src/reducers/data/todoReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import { TodoState } from '../../constants/models';
3 |
4 | import {
5 | CREATE_TODO,
6 | DELETE_TODO,
7 | CHANGE_TEXT,
8 | } from '../../constants/actionTypes';
9 |
10 | const todoReducers = handleActions({
11 | CREATE_TODO: (state) => {
12 | let todos = state.get('todos').push(state.get('todo'));
13 | return state.set('todos', todos)
14 | },
15 | DELETE_TODO: (state, { payload }) => (
16 | state.set('todos', state.get('todos').splice(payload.index, 1))
17 | ),
18 | CHANGE_TEXT: (state, { payload }) => (
19 | state.merge({ 'todo': payload })
20 | )
21 | }, TodoState);
22 |
23 | export default todoReducers;
24 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/src/reducers/data/todoReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import { TodoState } from '../../constants/models';
3 |
4 | import {
5 | CREATE_TODO,
6 | DELETE_TODO,
7 | CHANGE_TEXT,
8 | } from '../../constants/actionTypes';
9 |
10 | const todoReducers = handleActions({
11 | CREATE_TODO: (state) => {
12 | let todos = state.get('todos').push(state.get('todo'));
13 | return state.set('todos', todos)
14 | },
15 | DELETE_TODO: (state, { payload }) => (
16 | state.set('todos', state.get('todos').splice(payload.index, 1))
17 | ),
18 | CHANGE_TEXT: (state, { payload }) => (
19 | state.merge({ 'todo': payload })
20 | )
21 | }, TodoState);
22 |
23 | export default todoReducers;
24 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/routes/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Route, IndexRoute } from 'react-router';
3 | import Main from '../components/Main';
4 | import CheckAuth from '../components/CheckAuth';
5 | import HomePageContainer from '../containers/HomePageContainer';
6 | import LoginPageContainer from '../containers/LoginPageContainer';
7 | import SharePageContainer from '../containers/SharePageContainer';
8 |
9 | export default (
10 |
11 |
12 |
13 |
14 |
15 | );
16 |
--------------------------------------------------------------------------------
/Ch03/todo-examples/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 | *.pid.lock
11 |
12 | # Directory for instrumented libs generated by jscoverage/JSCover
13 | lib-cov
14 |
15 | # Coverage directory used by tools like istanbul
16 | coverage
17 |
18 | # nyc test coverage
19 | .nyc_output
20 |
21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
22 | .grunt
23 |
24 | # node-waf configuration
25 | .lock-wscript
26 |
27 | # Compiled binary addons (http://nodejs.org/api/addons.html)
28 | build/Release
29 |
30 | # Dependency directories
31 | node_modules
32 | jspm_packages
33 |
34 | # Optional npm cache directory
35 | .npm
36 |
37 | # Optional REPL history
38 | .node_repl_history
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/components/Counter/Counter.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react'
2 |
3 | const Counter = ({
4 | count,
5 | onIncrement,
6 | onDecrement,
7 | }) => (
8 |
9 | Clicked: {count} times
10 | {' '}
11 |
14 | {' '}
15 |
18 | {' '}
19 |
20 | );
21 |
22 | Counter.propTypes = {
23 | count: PropTypes.number.isRequired,
24 | onIncrement: PropTypes.func.isRequired,
25 | onDecrement: PropTypes.func.isRequired
26 | }
27 |
28 | Counter.defaultProps = {
29 | count: 0,
30 | onIncrement: () => {},
31 | onDecrement: () => {}
32 | }
33 |
34 | export default Counter;
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.1'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | mavenLocal()
18 | jcenter()
19 | maven {
20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
21 | url "$rootDir/../node_modules/react-native/android"
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/test/renderIntoDocument.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TestUtils from 'react-addons-test-utils';
3 | import { expect } from 'chai';
4 | import { findDOMNode } from 'react-dom';
5 | import TodoHeader from '../src/components/TodoHeader';
6 |
7 | describe('Simulate Event', () => {
8 | it('When click the button, it will be toggle', () => {
9 | const TodoHeaderApp = TestUtils.renderIntoDocument();
10 | const TodoHeaderDOM = findDOMNode(TodoHeaderApp);
11 | const button = TodoHeaderDOM.querySelector('button');
12 | TestUtils.Simulate.click(button);
13 | let todoHeaderButtonAfterClick = TodoHeaderDOM.querySelector('button').disabled;
14 | expect(todoHeaderButtonAfterClick).to.equal(true);
15 | });
16 | });
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/common/store/configureStore.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware } from 'redux';
2 | import thunk from 'redux-thunk';
3 | import createLogger from 'redux-logger';
4 | import rootReducer from '../reducers';
5 |
6 | export default function configureStore(preloadedState) {
7 | const store = createStore(
8 | rootReducer,
9 | preloadedState,
10 | applyMiddleware(createLogger({ stateTransformer: state => state.toJS() }), thunk)
11 | )
12 |
13 | if (module.hot) {
14 | // Enable Webpack hot module replacement for reducers
15 | module.hot.accept('../reducers', () => {
16 | const nextRootReducer = require('../reducers').default
17 | store.replaceReducer(nextRootReducer)
18 | })
19 | }
20 |
21 | return store
22 | }
23 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.1'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | mavenLocal()
18 | jcenter()
19 | maven {
20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
21 | url "$rootDir/../node_modules/react-native/android"
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/webpack.config.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 |
3 | module.exports = {
4 | entry: [
5 | './src/client/index.js',
6 | ],
7 | output: {
8 | path: `${__dirname}/dist`,
9 | filename: 'bundle.js',
10 | publicPath: '/static/'
11 | },
12 | module: {
13 | preLoaders: [
14 | {
15 | test: /\.jsx$|\.js$/,
16 | loader: 'eslint-loader',
17 | include: `${__dirname}/app`,
18 | exclude: /bundle\.js$/,
19 | },
20 | ],
21 | plugins: [
22 | new webpack.optimize.OccurrenceOrderPlugin(),
23 | new webpack.HotModuleReplacementPlugin()
24 | ],
25 | loaders: [{
26 | test: /\.js$/,
27 | exclude: /node_modules/,
28 | loader: 'babel-loader',
29 | }],
30 | },
31 | };
32 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/reducers/data/mottoReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import {
3 | MottoState
4 | } from '../../constants/models';
5 |
6 | import {
7 | GET_MOTTOS,
8 | CREATE_MOTTO,
9 | SET_IN_MOTTO,
10 | } from '../../constants/actionTypes';
11 |
12 | const mottoReducers = handleActions({
13 | GET_MOTTOS: (state, { payload }) => (
14 | state.set(
15 | 'mottos',
16 | payload.mottos
17 | )
18 | ),
19 | CREATE_MOTTO: (state) => (
20 | state.set(
21 | 'mottos',
22 | state.get('mottos').push(state.get('motto'))
23 | )
24 | ),
25 | SET_IN_MOTTO: (state, { payload }) => (
26 | state.setIn(
27 | payload.path,
28 | payload.value
29 | )
30 | )
31 | }, MottoState);
32 |
33 | export default mottoReducers;
--------------------------------------------------------------------------------
/Ch02/webpack-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webpack-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "webpack.config.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "dev": "webpack-dev-server --devtool eval --progress --colors --content-base build"
9 |
10 | },
11 | "author": "kdchang",
12 | "license": "MIT",
13 | "dependencies": {
14 | "react": "^15.2.1",
15 | "react-dom": "^15.2.1"
16 | },
17 | "devDependencies": {
18 | "babel-core": "^6.10.4",
19 | "babel-eslint": "^6.0.4",
20 | "babel-loader": "^6.2.4",
21 | "babel-preset-es2015": "^6.9.0",
22 | "babel-preset-react": "^6.11.1",
23 | "html-webpack-plugin": "^2.22.0",
24 | "webpack": "^1.13.1",
25 | "webpack-dev-server": "^1.14.1"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Ch03/todo-examples/app/components/TodoHeader/TodoHeader.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import styles from './todoHeaderStyles';
3 |
4 | const TodoHeader = (props) => (
5 |
6 |
TodoHeader
7 |
13 |
14 |
15 | );
16 |
17 | TodoHeader.propTypes = {
18 | todo: PropTypes.object,
19 | onTodoTextChange: PropTypes.func,
20 | onAddTodo: PropTypes.func,
21 | };
22 |
23 | TodoHeader.defaultProps = {
24 | todo: {},
25 | onTodoTextChange: () => {},
26 | onAddTodo: () => {},
27 | };
28 |
29 | export default TodoHeader;
30 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/ios/HelloWorldApp/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/Ch02/webpack-example/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin');
2 |
3 | const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
4 | template: `${__dirname}/app/index.html`,
5 | filename: 'index.html',
6 | inject: 'body',
7 | });
8 |
9 | module.exports = {
10 | entry: [
11 | './app/index.js',
12 | ],
13 | output: {
14 | path: `${__dirname}/dist`,
15 | filename: 'index_bundle.js',
16 | },
17 | module: {
18 | loaders: [
19 | {
20 | test: /\.js$/,
21 | exclude: /node_modules/,
22 | loader: 'babel-loader',
23 | query: {
24 | presets: ['es2015', 'react'],
25 | },
26 | },
27 | ],
28 | },
29 | devServer: {
30 | inline: true,
31 | port: 8008,
32 | },
33 | plugins: [HTMLWebpackPluginConfig],
34 | };
35 |
--------------------------------------------------------------------------------
/Ch02/browserify-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "browserify-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "kdchang",
10 | "license": "MIT",
11 | "dependencies": {
12 | "gulp": "^3.9.1",
13 | "react": "^15.2.1",
14 | "react-dom": "^15.2.1"
15 | },
16 | "devDependencies": {
17 | "babel-preset-es2015": "^6.9.0",
18 | "babel-preset-react": "^6.11.1",
19 | "babelify": "^7.3.0",
20 | "browserify": "^13.0.1",
21 | "gulp": "^3.9.1",
22 | "gulp-concat": "^2.6.0",
23 | "gulp-html-replace": "^1.6.1",
24 | "gulp-streamify": "^1.0.2",
25 | "gulp-uglify": "^1.5.4",
26 | "vinyl-source-stream": "^1.1.0",
27 | "watchify": "^3.7.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/client/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import { browserHistory, Router } from 'react-router';
5 | import { fromJS } from 'immutable';
6 | import routes from '../common/routes';
7 | import configureStore from '../common/store/configureStore';
8 | import { checkAuth } from '../common/actions';
9 |
10 | // get initial state from server side
11 | const initialState = window.__PRELOADED_STATE__;
12 |
13 | // use initial state to create store and pass to provider
14 | const store = configureStore(fromJS(initialState));
15 | ReactDOM.render(
16 |
17 |
18 | ,
19 | document.getElementById('app')
20 | );
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/components/App/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link, IndexLink } from 'react-router';
3 | import styles from './appStyles';
4 | import NavLink from '../NavLink';
5 |
6 | const App = (props) => (
7 |
8 |
React Router Tutorial
9 |
10 | - Home
11 | - About
12 | - Repos
13 | - User
14 | - Contacts
15 |
16 | {props.children}
17 |
18 | );
19 |
20 | App.propTypes = {
21 | children: React.PropTypes.object,
22 | };
23 |
24 | export default App;
25 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/ios/ReactNativeFirebaseMotto/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/Ch05/react-router-example/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Router, Route, hashHistory, IndexRoute } from 'react-router';
4 | import App from './components/App';
5 | import Home from './components/Home';
6 | import Repos from './components/Repos';
7 | import About from './components/About';
8 | import User from './components/User';
9 | import Contacts from './components/Contacts';
10 |
11 | ReactDOM.render(
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | ,
21 | document.getElementById('app'));
22 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/AppBarContainer/AppBarContainer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import AppBar from '../../components/AppBar';
4 | import { browserHistory } from 'react-router';
5 |
6 | import {
7 | startLogout,
8 | setRecipe,
9 | setUi,
10 | } from '../../actions';
11 |
12 | export default connect(
13 | (state) => ({
14 | isAuthorized: state.getIn(['user', 'isAuthorized']),
15 | }),
16 | (dispatch) => ({
17 | onToShare: () => {
18 | dispatch(setRecipe({ key: 'recipeId', value: '' }));
19 | dispatch(setUi({ key: 'isEdit', value: false }));
20 | window.location.reload();
21 | browserHistory.push('/share');
22 | },
23 | onLogout: () => (
24 | dispatch(startLogout(dispatch))
25 | ),
26 | })
27 | )(AppBar);
28 |
29 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/containers/HomePageContainer/HomePageContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 | import HomePage from '../../components/HomePage';
3 |
4 | import {
5 | getGithub,
6 | changeUserId,
7 | } from '../../actions';
8 |
9 | export default connect(
10 | state => ({
11 | userId: state.getIn(['github', 'userId']),
12 | }),
13 | dispatch => ({
14 | onChangeUserId: event => (
15 | dispatch(changeUserId(event.target.value))
16 | ),
17 | onSubmitUserId: userId => () => (
18 | dispatch(getGithub(userId))
19 | ),
20 | }),
21 | (stateProps, dispatchProps, ownProps) => {
22 | const { userId } = stateProps;
23 | const { onSubmitUserId } = dispatchProps;
24 | return Object.assign({}, stateProps, dispatchProps, ownProps, {
25 | onSubmitUserId: onSubmitUserId(userId),
26 | });
27 | }
28 | )(HomePage);
29 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/ios/HelloWorldAppTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/InputModal/inputModelStyles.js:
--------------------------------------------------------------------------------
1 | import { StyleSheet } from 'react-native';
2 |
3 | export default StyleSheet.create({
4 | modalHeader: {
5 | flex: 1,
6 | height: 30,
7 | padding: 10,
8 | flexDirection: 'row',
9 | backgroundColor: '#ffc107',
10 | fontSize: 20,
11 | },
12 | buttonContainer: {
13 | flex: 1,
14 | flexDirection: 'row',
15 | },
16 | button: {
17 | borderRadius: 5,
18 |
19 | },
20 | cancelButton: {
21 | flex: 1,
22 | height: 40,
23 | alignItems: 'center',
24 | justifyContent: 'center',
25 | backgroundColor: '#eceff1',
26 | margin: 5,
27 | },
28 | submitButton: {
29 | flex: 1,
30 | height: 40,
31 | alignItems: 'center',
32 | justifyContent: 'center',
33 | backgroundColor: '#4fc3f7',
34 | margin: 5,
35 | },
36 | buttonText: {
37 | fontSize: 20,
38 | }
39 | });
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/actions/githubActions.js:
--------------------------------------------------------------------------------
1 | import 'whatwg-fetch';
2 | import {
3 | GET_GITHUB_INITIATE,
4 | GET_GITHUB_SUCCESS,
5 | GET_GITHUB_FAIL,
6 | CHAGE_USER_ID,
7 | } from '../constants/actionTypes';
8 |
9 | import {
10 | showSpinner,
11 | hideSpinner,
12 | } from './uiActions';
13 |
14 | export const getGithub = (userId = 'torvalds') => (
15 | (dispatch) => {
16 | dispatch({ type: GET_GITHUB_INITIATE });
17 | dispatch(showSpinner());
18 | fetch(`https://api.github.com/users/${userId}`)
19 | .then(response => response.json())
20 | .then((json) => {
21 | dispatch({ type: GET_GITHUB_SUCCESS, payload: { data: json } });
22 | dispatch(hideSpinner());
23 | })
24 | .catch(() => dispatch({ type: GET_GITHUB_FAIL }));
25 | }
26 | );
27 |
28 | export const changeUserId = text => ({ type: CHAGE_USER_ID, payload: { userId: text } });
29 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin');
2 |
3 | const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
4 | template: `${__dirname}/src/index.html`,
5 | filename: 'index.html',
6 | inject: 'body',
7 | });
8 |
9 | module.exports = {
10 | entry: [
11 | './src/index.js',
12 | ],
13 | output: {
14 | path: `${__dirname}/dist`,
15 | filename: 'index_bundle.js',
16 | },
17 | module: {
18 | preLoaders: [
19 | {
20 | test: /\.jsx$|\.js$/,
21 | loader: 'eslint-loader',
22 | include: `${__dirname}/src`,
23 | exclude: /bundle\.js$/
24 | }
25 | ],
26 | loaders: [{
27 | test: /\.js$/,
28 | exclude: /node_modules/,
29 | loader: 'babel-loader',
30 | }],
31 | },
32 | devServer: {
33 | inline: true,
34 | port: 8008,
35 | },
36 | plugins: [HTMLWebpackPluginConfig],
37 | };
--------------------------------------------------------------------------------
/Ch07/react-flux-example/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin');
2 |
3 | const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
4 | template: `${__dirname}/src/index.html`,
5 | filename: 'index.html',
6 | inject: 'body',
7 | });
8 |
9 | module.exports = {
10 | entry: [
11 | './src/index.js',
12 | ],
13 | output: {
14 | path: `${__dirname}/dist`,
15 | filename: 'index_bundle.js',
16 | },
17 | module: {
18 | preLoaders: [
19 | {
20 | test: /\.jsx$|\.js$/,
21 | loader: 'eslint-loader',
22 | include: `${__dirname}/src`,
23 | exclude: /bundle\.js$/,
24 | },
25 | ],
26 | loaders: [{
27 | test: /\.js$/,
28 | exclude: /node_modules/,
29 | loader: 'babel-loader',
30 | }],
31 | },
32 | devServer: {
33 | inline: true,
34 | port: 8008,
35 | },
36 | plugins: [HTMLWebpackPluginConfig],
37 | };
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/components/HomePage/HomePage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router';
3 | import RaisedButton from 'material-ui/RaisedButton';
4 | import TextField from 'material-ui/TextField';
5 |
6 | const HomePage = ({
7 | userId,
8 | onSubmitUserId,
9 | onChangeUserId,
10 | }) => (
11 |
12 |
16 |
22 |
23 |
24 |
25 | );
26 |
27 | HomePage.propTypes = {
28 | onSubmitUserId: React.PropTypes.func,
29 | onChangeUserId: React.PropTypes.func,
30 | userId: React.PropTypes.string,
31 | };
32 |
33 | export default HomePage;
34 |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/src/components/TodoList/TodoList.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import TodoStore from '../../stores/TodoStore';
3 |
4 | function getAppState() {
5 | return {
6 | todos: TodoStore.getTodos(),
7 | };
8 | }
9 | class TodoList extends Component {
10 | constructor(props) {
11 | super(props);
12 | this.onChange = this.onChange.bind(this);
13 | this.state = {
14 | todos: [],
15 | };
16 | }
17 | componentDidMount() {
18 | TodoStore.addChangeListener(this.onChange);
19 | }
20 | onChange() {
21 | this.setState(getAppState());
22 | }
23 | render() {
24 | return (
25 |
26 |
27 | {
28 | this.state.todos.map((todo, key) => (
29 | - {todo}
30 | ))
31 | }
32 |
33 |
34 | );
35 | }
36 | }
37 |
38 | export default TodoList;
39 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/ios/ReactNativeFirebaseMottoTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/test/shallowRenderProps.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TestUtils from 'react-addons-test-utils';
3 | import { expect } from 'chai';
4 | import TodoList from '../src/components/TodoList';
5 |
6 | const shallowRender = (Component, props) => {
7 | const renderer = TestUtils.createRenderer();
8 | renderer.render();
9 | return renderer.getRenderOutput();
10 | }
11 |
12 | describe('Shallow Props Rendering', () => {
13 | it('TodoList props check', () => {
14 | const todos = [{ id: 0, text: 'reading'}, { id: 1, text: 'coding'}];
15 | const todoList = shallowRender(TodoList, {todos: todos});
16 | expect(todoList.props.children.type).to.equal('ul');
17 | expect(todoList.props.children.props.children[0].props.children).to.equal('reading');
18 | expect(todoList.props.children.props.children[1].props.children).to.equal('coding');
19 | });
20 | });
--------------------------------------------------------------------------------
/Ch07/react-redux-example/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin');
2 |
3 | const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
4 | template: `${__dirname}/src/index.html`,
5 | filename: 'index.html',
6 | inject: 'body',
7 | });
8 |
9 | module.exports = {
10 | entry: [
11 | './src/index.js',
12 | ],
13 | output: {
14 | path: `${__dirname}/dist`,
15 | filename: 'index_bundle.js',
16 | },
17 | module: {
18 | preLoaders: [
19 | {
20 | test: /\.jsx$\\.js$/,
21 | loader: 'eslint-loader',
22 | include: `${__dirname}/src`,
23 | exclude: /bundle\.js$/,
24 | },
25 | ],
26 | loaders: [{
27 | test: /\.js$/,
28 | exclude: /node_modules/,
29 | loader: 'babel-loader',
30 | }],
31 | },
32 | devServer: {
33 | inline: true,
34 | port: 8008,
35 | },
36 | plugins: [HTMLWebpackPluginConfig],
37 | };
38 |
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/webpack.config.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 |
3 | module.exports = {
4 | entry: [
5 | './client/index.js',
6 | ],
7 | output: {
8 | path: `${__dirname}/dist`,
9 | filename: 'bundle.js',
10 | publicPath: '/static/'
11 | },
12 | module: {
13 | preLoaders: [
14 | {
15 | test: /\.jsx$|\.js$/,
16 | loader: 'eslint-loader',
17 | include: `${__dirname}/app`,
18 | exclude: /bundle\.js$/,
19 | },
20 | ],
21 | // 優化並使用 HotModuleReplacement
22 | // plugins: [
23 | // new webpack.optimize.OccurrenceOrderPlugin(),
24 | // new webpack.HotModuleReplacementPlugin()
25 | // ],
26 | loaders: [{
27 | test: /\.js$/,
28 | exclude: /node_modules/,
29 | loader: 'babel-loader',
30 | query: {
31 | presets: ['es2015', 'react', 'react-hmre'],
32 | },
33 | }],
34 | },
35 | };
36 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/RecipeBox/RecipeBox.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Grid, Row, Col, Image, Thumbnail, Button } from 'react-bootstrap';
3 |
4 | const RecipeBox = (props) => {
5 | return(
6 |
7 |
8 | {props.recipe.get('name')}
9 | {props.recipe.get('description')}
10 | {
11 | props.isAuthorized === true ? (
12 |
13 |
14 |
15 |
)
16 | : null
17 | }
18 |
19 |
20 | );
21 | }
22 |
23 | export default RecipeBox;
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin');
2 |
3 | const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
4 | template: `${__dirname}/src/index.html`,
5 | filename: 'index.html',
6 | inject: 'body',
7 | });
8 |
9 | module.exports = {
10 | entry: [
11 | './src/index.js',
12 | ],
13 | output: {
14 | path: `${__dirname}/dist`,
15 | filename: 'index_bundle.js',
16 | },
17 | module: {
18 | preLoaders: [
19 | {
20 | test: /\.jsx$|\.js$/,
21 | loader: 'eslint-loader',
22 | include: `${__dirname}/src`,
23 | exclude: /bundle\.js$/
24 | }
25 | ],
26 | loaders: [{
27 | test: /\.js$/,
28 | exclude: /node_modules/,
29 | loader: 'babel-loader',
30 | }],
31 | },
32 | devServer: {
33 | inline: true,
34 | port: 8008,
35 | },
36 | plugins: [HTMLWebpackPluginConfig],
37 | };
--------------------------------------------------------------------------------
/Ch02/cdn-example/hello.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello React!
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-flux-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --colors --inline --content-base ."
8 | },
9 | "author": "kdchang",
10 | "license": "MIT",
11 | "devDependencies": {
12 | "babel-core": "^6.11.4",
13 | "babel-eslint": "^6.1.2",
14 | "babel-loader": "^6.2.4",
15 | "babel-preset-es2015": "^6.9.0",
16 | "babel-preset-react": "^6.11.1",
17 | "eslint": "^3.2.0",
18 | "eslint-config-airbnb": "^9.0.1",
19 | "eslint-loader": "^1.5.0",
20 | "eslint-plugin-import": "^1.12.0",
21 | "eslint-plugin-jsx-a11y": "^2.0.1",
22 | "eslint-plugin-react": "^5.2.2",
23 | "html-webpack-plugin": "^2.22.0",
24 | "webpack": "^1.13.1",
25 | "webpack-dev-server": "^1.14.1"
26 | },
27 | "dependencies": {
28 | "flux": "^2.1.1",
29 | "react": "^15.3.0",
30 | "react-dom": "^15.3.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/src/stores/TodoStore.js:
--------------------------------------------------------------------------------
1 | import AppDispatcher from '../dispatcher/AppDispatcher';
2 | import { ADD_TODO } from '../constants/actionTypes';
3 | import { EventEmitter } from 'events';
4 |
5 | // const CHANGE_EVENT = 'change';
6 |
7 | const store = {
8 | todos: [],
9 | editing: false,
10 | };
11 |
12 | class TodoStoreClass extends EventEmitter {
13 |
14 | addChangeListener(callback) {
15 | this.on(ADD_TODO, callback);
16 | }
17 |
18 | removeChangeListener(callback) {
19 | this.removeListener(ADD_TODO, callback);
20 | }
21 |
22 | getTodos() {
23 | return store.todos;
24 | }
25 | }
26 |
27 | const TodoStore = new TodoStoreClass();
28 |
29 | AppDispatcher.register((action) => {
30 | switch (action.type) {
31 | case ADD_TODO:
32 | store.todos.push(action.payload.text);
33 | TodoStore.emit(ADD_TODO);
34 | break;
35 | default:
36 | return true;
37 | }
38 | return true;
39 | });
40 |
41 | export default TodoStore;
42 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | android.useDeprecatedNdk=true
21 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ReactNativeFirebaseMotto",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "start": "node node_modules/react-native/local-cli/cli.js start"
7 | },
8 | "dependencies": {
9 | "firebase": "^3.3.0",
10 | "immutable": "^3.8.1",
11 | "react": "15.3.1",
12 | "react-native": "0.32.0",
13 | "react-native-vector-icons": "^2.1.0",
14 | "react-redux": "^4.4.5",
15 | "redux": "^3.5.2",
16 | "redux-actions": "^0.11.0",
17 | "redux-immutable": "^3.0.8",
18 | "uuid": "^2.0.2"
19 | },
20 | "devDependencies": {
21 | "babel-core": "^6.14.0",
22 | "babel-eslint": "^6.1.2",
23 | "babel-loader": "^6.2.5",
24 | "babel-preset-es2015": "^6.14.0",
25 | "babel-preset-react": "^6.11.1",
26 | "babel-preset-react-native": "^1.9.0",
27 | "babel-preset-stage-1": "^6.13.0",
28 | "eslint-plugin-react-native": "^2.0.0",
29 | "redux-logger": "^2.6.1"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin');
2 |
3 | const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
4 | template: `${__dirname}/src/index.html`,
5 | filename: 'index.html',
6 | inject: 'body',
7 | });
8 |
9 | module.exports = {
10 | entry: [
11 | './src/index.js',
12 | ],
13 | output: {
14 | path: `${__dirname}/dist`,
15 | filename: 'index_bundle.js',
16 | },
17 | module: {
18 | preLoaders: [
19 | {
20 | test: /\.jsx$|\.js$/,
21 | loader: 'eslint-loader',
22 | include: `${__dirname}/src`,
23 | exclude: /bundle\.js$/
24 | }
25 | ],
26 | loaders: [{
27 | test: /\.js$/,
28 | exclude: /node_modules/,
29 | loader: 'babel-loader',
30 | query: {
31 | presets: ['es2015', 'react'],
32 | },
33 | }],
34 | },
35 | devServer: {
36 | inline: true,
37 | port: 8008,
38 | },
39 | plugins: [HTMLWebpackPluginConfig],
40 | };
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | android.useDeprecatedNdk=true
21 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin');
2 |
3 | const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
4 | template: `${__dirname}/src/index.html`,
5 | filename: 'index.html',
6 | inject: 'body',
7 | });
8 |
9 | module.exports = {
10 | entry: [
11 | './src/index.js',
12 | ],
13 | output: {
14 | path: `${__dirname}/dist`,
15 | filename: 'index_bundle.js',
16 | },
17 | module: {
18 | preLoaders: [
19 | {
20 | test: /\.jsx$\\.js$/,
21 | loader: 'eslint-loader',
22 | include: `${__dirname}/src`,
23 | exclude: /bundle\.js$/
24 | }
25 | ],
26 | loaders: [{
27 | test: /\.js$/,
28 | exclude: /node_modules/,
29 | loader: 'babel-loader',
30 | query: {
31 | presets: ['es2015', 'react'],
32 | },
33 | }],
34 | },
35 | devServer: {
36 | inline: true,
37 | port: 8008,
38 | },
39 | plugins: [HTMLWebpackPluginConfig],
40 | }
41 |
--------------------------------------------------------------------------------
/Ch05/react-router-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-router-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "webpack.config.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --colors --inline --content-base ."
8 | },
9 | "author": "kdchang",
10 | "license": "MIT",
11 | "dependencies": {
12 | "react": "^15.3.1",
13 | "react-dom": "^15.3.1",
14 | "react-router": "^2.7.0"
15 | },
16 | "devDependencies": {
17 | "babel-core": "^6.13.2",
18 | "babel-eslint": "^6.1.2",
19 | "babel-loader": "^6.2.5",
20 | "babel-preset-es2015": "^6.13.2",
21 | "babel-preset-react": "^6.11.1",
22 | "eslint": "^3.3.1",
23 | "eslint-config-airbnb": "^10.0.1",
24 | "eslint-loader": "^1.5.0",
25 | "eslint-plugin-import": "^1.13.0",
26 | "eslint-plugin-jsx-a11y": "^2.1.0",
27 | "eslint-plugin-react": "^6.1.2",
28 | "html-webpack-plugin": "^2.22.0",
29 | "webpack": "^1.13.2",
30 | "webpack-dev-server": "^1.14.1"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin');
2 |
3 | const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
4 | template: `${__dirname}/src/index.html`,
5 | filename: 'index.html',
6 | inject: 'body',
7 | });
8 |
9 | module.exports = {
10 | entry: [
11 | './src/index.js',
12 | ],
13 | output: {
14 | path: `${__dirname}/dist`,
15 | filename: 'index_bundle.js',
16 | },
17 | module: {
18 | preLoaders: [
19 | {
20 | test: /\.jsx$\\.js$/,
21 | loader: 'eslint-loader',
22 | include: `${__dirname}/src`,
23 | exclude: /bundle\.js$/
24 | }
25 | ],
26 | loaders: [{
27 | test: /\.js$/,
28 | exclude: /node_modules/,
29 | loader: 'babel-loader',
30 | query: {
31 | presets: ['es2015', 'react'],
32 | },
33 | }],
34 | },
35 | devServer: {
36 | inline: true,
37 | port: 8008,
38 | },
39 | plugins: [HTMLWebpackPluginConfig],
40 | }
41 |
--------------------------------------------------------------------------------
/Ch03/todo-examples/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "enviroment-setup",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "directories": {
7 | "example": "examples"
8 | },
9 | "scripts": {
10 | "start": "webpack-dev-server --colors --inline --content-base ."
11 | },
12 | "author": "kdchang",
13 | "license": "MIT",
14 | "devDependencies": {
15 | "babel-core": "^6.10.4",
16 | "babel-eslint": "^6.0.4",
17 | "babel-loader": "^6.2.4",
18 | "babel-preset-es2015": "^6.9.0",
19 | "babel-preset-react": "^6.11.1",
20 | "babel-preset-stage-0": "^6.5.0",
21 | "eslint": "^2.13.1",
22 | "eslint-config-airbnb": "^9.0.1",
23 | "eslint-plugin-import": "^1.8.0",
24 | "eslint-plugin-jsx-a11y": "^1.2.0",
25 | "eslint-plugin-react": "^5.1.1",
26 | "gulp": "^3.9.1",
27 | "gulp-eslint": "^2.0.0",
28 | "gulp-if": "^2.0.1",
29 | "html-webpack-plugin": "^2.22.0",
30 | "webpack": "^1.13.1",
31 | "webpack-dev-server": "^1.14.1"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/app/src/main/java/com/helloworldapp/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.helloworldapp;
2 |
3 | import android.app.Application;
4 | import android.util.Log;
5 |
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.facebook.react.ReactPackage;
10 | import com.facebook.react.shell.MainReactPackage;
11 |
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 | public class MainApplication extends Application implements ReactApplication {
16 |
17 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
18 | @Override
19 | protected boolean getUseDeveloperSupport() {
20 | return BuildConfig.DEBUG;
21 | }
22 |
23 | @Override
24 | protected List getPackages() {
25 | return Arrays.asList(
26 | new MainReactPackage()
27 | );
28 | }
29 | };
30 |
31 | @Override
32 | public ReactNativeHost getReactNativeHost() {
33 | return mReactNativeHost;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { Provider } from 'react-redux';
4 | import { browserHistory, Router, Route, IndexRoute } from 'react-router';
5 | import injectTapEventPlugin from 'react-tap-event-plugin';
6 | import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
7 | import Main from './components/Main';
8 | import HomePageContainer from './containers/HomePageContainer';
9 | import ResultPageContainer from './containers/ResultPageContainer';
10 | import store from './store';
11 |
12 | // Needed for onTouchTap
13 | // http://stackoverflow.com/a/34015469/988941
14 | injectTapEventPlugin();
15 |
16 | ReactDOM.render(
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | ,
27 | document.getElementById('app')
28 | );
29 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/java/com/reactnativefirebasemotto/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.reactnativefirebasemotto;
2 |
3 | import android.app.Application;
4 | import android.util.Log;
5 |
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.facebook.react.ReactPackage;
10 | import com.facebook.react.shell.MainReactPackage;
11 |
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 | public class MainApplication extends Application implements ReactApplication {
16 |
17 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
18 | @Override
19 | protected boolean getUseDeveloperSupport() {
20 | return BuildConfig.DEBUG;
21 | }
22 |
23 | @Override
24 | protected List getPackages() {
25 | return Arrays.asList(
26 | new MainReactPackage()
27 | );
28 | }
29 | };
30 |
31 | @Override
32 | public ReactNativeHost getReactNativeHost() {
33 | return mReactNativeHost;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/AppBar/AppBar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { LinkContainer } from 'react-router-bootstrap';
3 | import { Link } from 'react-router';
4 | import { Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';
5 |
6 | const AppBar = ({
7 | isAuthorized,
8 | onToShare,
9 | onLogout,
10 | }) => (
11 |
12 |
13 |
14 | OpenCook
15 |
16 |
17 |
18 |
19 | {
20 | isAuthorized === false ?
21 | (
22 |
25 | ) :
26 | (
27 |
31 | )
32 | }
33 |
34 |
35 | );
36 |
37 | export default AppBar;
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/src/components/GithubBox/GithubBox.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router';
3 | import { Card, CardActions, CardHeader, CardText } from 'material-ui/Card';
4 | import RaisedButton from 'material-ui/RaisedButton';
5 | import ActionHome from 'material-ui/svg-icons/action/home';
6 |
7 | const GithubBox = props => (
8 |
9 |
10 |
15 |
16 | Followers : {props.data.get('followers')}
17 |
18 |
19 | Following : {props.data.get('following')}
20 |
21 |
22 |
23 | }
26 | secondary
27 | />
28 |
29 |
30 |
31 |
32 | );
33 |
34 | GithubBox.propTypes = {
35 | data: React.PropTypes.Object,
36 | userId: React.PropTypes.string,
37 | };
38 |
39 | export default GithubBox;
40 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/reducers/data/userReducers.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions';
2 | import { UserState } from '../../constants/models';
3 |
4 | import {
5 | AUTH_START,
6 | AUTH_COMPLETE,
7 | AUTH_ERROR,
8 | LOGOUT_START,
9 | SET_USER,
10 | } from '../../constants/actionTypes';
11 |
12 | const userReducers = handleActions({
13 | AUTH_START: (state) => (
14 | state.merge({
15 | isAuthorized: false,
16 | })
17 | ),
18 | AUTH_COMPLETE: (state) => (
19 | state.merge({
20 | email: '',
21 | password: '',
22 | isAuthorized: true,
23 | })
24 | ),
25 | AUTH_ERROR: (state) => (
26 | state.merge({
27 | username: '',
28 | email: '',
29 | password: '',
30 | isAuthorized: false,
31 | })
32 | ),
33 | START_LOGOUT: (state) => (
34 | state.merge({
35 | isAuthorized: false,
36 | })
37 | ),
38 | CHECK_AUTH: (state) => (
39 | state.set('isAuthorized', true)
40 | ),
41 | SET_USER: (state, { payload }) => (
42 | state.set(payload.key, payload.value)
43 | ),
44 | }, UserState);
45 |
46 | export default userReducers;
47 |
--------------------------------------------------------------------------------
/Ch07/react-flux-example/src/components/TodoHeader/TodoHeader.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { TodoActions } from '../../actions/todoActions';
3 |
4 | class TodoHeader extends Component {
5 | constructor(props) {
6 | super(props);
7 | this.onChange = this.onChange.bind(this);
8 | this.onAdd = this.onAdd.bind(this);
9 | this.state = {
10 | text: '',
11 | editing: false,
12 | };
13 | }
14 |
15 | onChange(event) {
16 | this.setState({
17 | text: event.target.value,
18 | });
19 | }
20 |
21 | onAdd() {
22 | TodoActions.addTodo(this.state.text);
23 | this.setState({
24 | text: '',
25 | });
26 | }
27 |
28 | render() {
29 | return (
30 |
31 |
TodoFlux
32 |
33 |
39 |
44 |
45 |
46 | );
47 | }
48 | }
49 |
50 | export default TodoHeader;
51 |
52 |
--------------------------------------------------------------------------------
/Ch07/react-redux-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-redux-example",
3 | "version": "1.0.0",
4 | "description": "react-redux-example",
5 | "main": "webpack.config.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --colors --inline --content-base ."
8 | },
9 | "author": "kdchang",
10 | "license": "MIT",
11 | "dependencies": {
12 | "immutable": "^3.8.1",
13 | "react": "^15.3.0",
14 | "react-dom": "^15.3.0",
15 | "react-redux": "^4.4.5",
16 | "redux": "^3.5.2",
17 | "redux-actions": "^0.10.1",
18 | "redux-immutable": "^3.0.7",
19 | "uuid": "^2.0.2"
20 | },
21 | "devDependencies": {
22 | "babel-core": "^6.13.2",
23 | "babel-eslint": "^6.1.2",
24 | "babel-loader": "^6.2.4",
25 | "babel-preset-es2015": "^6.13.2",
26 | "babel-preset-react": "^6.11.1",
27 | "eslint": "^3.3.1",
28 | "eslint-config-airbnb": "^10.0.1",
29 | "eslint-loader": "^1.5.0",
30 | "eslint-plugin-import": "^1.13.0",
31 | "eslint-plugin-jsx-a11y": "^2.1.0",
32 | "eslint-plugin-react": "^6.1.1",
33 | "html-webpack-plugin": "^2.22.0",
34 | "redux-logger": "^2.6.1",
35 | "webpack": "^1.13.1",
36 | "webpack-dev-server": "^1.14.1"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Appendix03/react-mocha-test-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-mocha-test-example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "webpack.config.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "start": "webpack-dev-server --colors --inline --content-base .",
11 | "test": "mocha -t 5000 --compilers js:babel-core/register"
12 | },
13 | "author": "kdchang",
14 | "license": "MIT",
15 | "devDependencies": {
16 | "babel-core": "^6.14.0",
17 | "babel-eslint": "^6.1.2",
18 | "babel-loader": "^6.2.5",
19 | "babel-preset-es2015": "^6.14.0",
20 | "babel-preset-react": "^6.11.1",
21 | "chai": "^3.5.0",
22 | "eslint": "^3.4.0",
23 | "eslint-config-airbnb": "^10.0.1",
24 | "eslint-loader": "^1.5.0",
25 | "eslint-plugin-import": "^1.14.0",
26 | "eslint-plugin-jsx-a11y": "^2.2.1",
27 | "eslint-plugin-react": "^6.2.0",
28 | "html-webpack-plugin": "^2.22.0",
29 | "mocha": "^3.0.2",
30 | "webpack": "^1.13.2",
31 | "webpack-dev-server": "^1.15.1"
32 | },
33 | "dependencies": {
34 | "axios": "^0.14.0",
35 | "node-fetch": "^1.6.0",
36 | "react": "^15.3.1",
37 | "react-dom": "^15.3.1"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/Main/Main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactNative from 'react-native';
3 | import { Provider } from 'react-redux';
4 | import ToolBar from '../ToolBar';
5 | import MottoListContainer from '../../containers/MottoListContainer';
6 | import ActionButtonContainer from '../../containers/ActionButtonContainer';
7 | import InputModalContainer from '../../containers/InputModalContainer';
8 | import ListItem from '../ListItem';
9 | import * as firebase from 'firebase';
10 | import { firebaseConfig } from '../../constants/config';
11 | import store from '../../store';
12 | const { View, Text } = ReactNative;
13 |
14 | // Initialize Firebase
15 | const firebaseApp = firebase.initializeApp(firebaseConfig);
16 | // Create a reference with .ref() instead of new Firebase(url)
17 | const rootRef = firebaseApp.database().ref();
18 | const itemsRef = rootRef.child('items');
19 |
20 | const Main = () => (
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | );
30 |
31 | export default Main;
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/LoginBoxContainer/LoginBoxContainer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import LoginBox from '../../components/LoginBox';
4 |
5 | import {
6 | authStart,
7 | showSpinner,
8 | setUser,
9 | } from '../../actions';
10 |
11 | export default connect(
12 | (state) => ({
13 | email: state.getIn(['user', 'email']),
14 | password: state.getIn(['user', 'password']),
15 | }),
16 | (dispatch) => ({
17 | onChangeEmailInput: (event) => (
18 | dispatch(setUser({ key: 'email', value: event.target.value }))
19 | ),
20 | onChangePasswordInput: (event) => (
21 | dispatch(setUser({ key: 'password', value: event.target.value }))
22 | ),
23 | onLoginSubmit: (email, password) => () => {
24 | dispatch(authStart(dispatch, email, password));
25 | dispatch(showSpinner());
26 | },
27 | }),
28 | (stateProps, dispatchProps, ownProps) => {
29 | const { email, password } = stateProps;
30 | const { onLoginSubmit } = dispatchProps;
31 | return Object.assign({}, stateProps, dispatchProps, ownProps, {
32 | onLoginSubmit: onLoginSubmit(email, password),
33 | });
34 | }
35 | )(LoginBox);
36 |
37 |
--------------------------------------------------------------------------------
/Appendix03/react-addons-test-utils-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-redux-example",
3 | "version": "1.0.0",
4 | "description": "react-redux-example",
5 | "main": "webpack.config.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --colors --inline --content-base .",
8 | "test": "mocha --compilers js:babel-core/register --require ./test/setup.js --recursive"
9 | },
10 | "author": "kdchang",
11 | "license": "MIT",
12 | "dependencies": {
13 | "react": "^15.3.0",
14 | "react-dom": "^15.3.0"
15 | },
16 | "devDependencies": {
17 | "babel-core": "^6.13.2",
18 | "babel-eslint": "^6.1.2",
19 | "babel-loader": "^6.2.4",
20 | "babel-preset-es2015": "^6.14.0",
21 | "babel-preset-react": "^6.11.1",
22 | "chai": "^3.5.0",
23 | "enzyme": "^2.4.1",
24 | "eslint": "^3.3.1",
25 | "eslint-config-airbnb": "^10.0.1",
26 | "eslint-loader": "^1.5.0",
27 | "eslint-plugin-import": "^1.13.0",
28 | "eslint-plugin-jsx-a11y": "^2.1.0",
29 | "eslint-plugin-react": "^6.1.1",
30 | "html-webpack-plugin": "^2.22.0",
31 | "jsdom": "^9.5.0",
32 | "mocha": "^3.0.2",
33 | "react-addons-test-utils": "^15.3.1",
34 | "webpack": "^1.13.1",
35 | "webpack-dev-server": "^1.14.1"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/containers/MottoListContainer/MottoListContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 | import MottoList from '../../components/MottoList';
3 | import Immutable from 'immutable';
4 | import uuid from 'uuid';
5 |
6 | import {
7 | createMotto,
8 | getMottos,
9 | changeMottoTitle,
10 | } from '../../actions';
11 |
12 | export default connect(
13 | (state) => ({
14 | mottos: state.getIn(['motto', 'mottos']),
15 | }),
16 | (dispatch) => ({
17 | onCreateMotto: () => (
18 | dispatch(createMotto())
19 | ),
20 | onGetMottos: (mottos) => (
21 | dispatch(getMottos({ mottos }))
22 | ),
23 | onChangeMottoTitle: (title) => (
24 | dispatch(changeMottoTitle({ value: title }))
25 | ),
26 | onDeleteMotto: (mottos) => (id, itemsRef) => () => {
27 | mottos.forEach((value, key) => {
28 | if(value.get('id') === id) {
29 | itemsRef.child(key).remove();
30 | }
31 | });
32 | }
33 | }),
34 | (stateToProps, dispatchToProps, ownProps) => {
35 | const { mottos } = stateToProps;
36 | const { onDeleteMotto } = dispatchToProps;
37 | return Object.assign({}, stateToProps, dispatchToProps, ownProps, {
38 | onDeleteMotto: onDeleteMotto(mottos),
39 | });
40 | }
41 | )(MottoList);
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/LoginBox/LoginBox.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Form, FormGroup, Button, FormControl, ControlLabel } from 'react-bootstrap';
3 |
4 | const LoginBox = ({
5 | email,
6 | password,
7 | onChangeEmailInput,
8 | onChangePasswordInput,
9 | onLoginSubmit
10 | }) => (
11 |
12 |
44 |
45 | );
46 |
47 | export default LoginBox;
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/index.ios.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | * @flow
5 | */
6 |
7 | import React, { Component } from 'react';
8 | import {
9 | AppRegistry,
10 | StyleSheet,
11 | Text,
12 | View
13 | } from 'react-native';
14 |
15 | class HelloWorldApp extends Component {
16 | render() {
17 | return (
18 |
19 |
20 | Welcome to React Native!
21 |
22 |
23 | To get started, edit index.ios.js
24 |
25 |
26 | Press Cmd+R to reload,{'\n'}
27 | Cmd+D or shake for dev menu
28 |
29 |
30 | );
31 | }
32 | }
33 |
34 | const styles = StyleSheet.create({
35 | container: {
36 | flex: 1,
37 | justifyContent: 'center',
38 | alignItems: 'center',
39 | backgroundColor: '#F5FCFF',
40 | },
41 | welcome: {
42 | fontSize: 20,
43 | textAlign: 'center',
44 | margin: 10,
45 | },
46 | instructions: {
47 | textAlign: 'center',
48 | color: '#333333',
49 | marginBottom: 5,
50 | },
51 | });
52 |
53 | AppRegistry.registerComponent('HelloWorldApp', () => HelloWorldApp);
54 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/index.android.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | * @flow
5 | */
6 |
7 | import React, { Component } from 'react';
8 | import {
9 | AppRegistry,
10 | StyleSheet,
11 | Text,
12 | View
13 | } from 'react-native';
14 |
15 | class HelloWorldApp extends Component {
16 | render() {
17 | return (
18 |
19 |
20 | Welcome to React Native Rock!!!!
21 |
22 |
23 | To get started, edit index.android.js
24 |
25 |
26 | Double tap R on your keyboard to reload,{'\n'}
27 | Shake or press menu button for dev menu
28 |
29 |
30 | );
31 | }
32 | }
33 |
34 | const styles = StyleSheet.create({
35 | container: {
36 | flex: 1,
37 | justifyContent: 'center',
38 | alignItems: 'center',
39 | backgroundColor: '#F5FCFF',
40 | },
41 | welcome: {
42 | fontSize: 20,
43 | textAlign: 'center',
44 | margin: 10,
45 | },
46 | instructions: {
47 | textAlign: 'center',
48 | color: '#333333',
49 | marginBottom: 5,
50 | },
51 | });
52 |
53 | AppRegistry.registerComponent('HelloWorldApp', () => HelloWorldApp);
54 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/containers/InputModalContainer/InputModalContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 | import InputModal from '../../components/InputModal';
3 | import Immutable from 'immutable';
4 |
5 | import {
6 | toggleModal,
7 | setInMotto,
8 | createMotto,
9 | } from '../../actions';
10 | import uuid from 'uuid';
11 |
12 | export default connect(
13 | (state) => ({
14 | isModalVisible: state.getIn(['ui', 'isModalVisible']),
15 | motto: state.getIn(['motto', 'motto']),
16 | }),
17 | (dispatch) => ({
18 | onToggleModal: () => (
19 | dispatch(toggleModal())
20 | ),
21 | onChangeMottoText: (text) => (
22 | dispatch(setInMotto({ path: ['motto', 'text'], value: text }))
23 | ),
24 | onCreateMotto: (motto) => (itemsRef) => () => {
25 | itemsRef.push({ id: uuid.v4(), text: motto.get('text'), updatedAt: Date.now() });
26 | dispatch(setInMotto({ path: ['motto'], value: Immutable.fromJS({ id: '', text: '', updatedAt: '' })}));
27 | dispatch(toggleModal());
28 | }
29 | }),
30 | (stateToProps, dispatchToProps, ownProps) => {
31 | const { motto } = stateToProps;
32 | const { onCreateMotto } = dispatchToProps;
33 | return Object.assign({}, stateToProps, dispatchToProps, ownProps, {
34 | onCreateMotto: onCreateMotto(motto),
35 | });
36 | },
37 | )(InputModal);
38 |
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/components/CheckAuth/CheckAuth.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import { withRouter } from 'react-router';
4 |
5 | // High Order Component
6 | export default function requireAuthentication(Component, type) {
7 | class AuthenticatedComponent extends React.Component {
8 | componentWillMount() {
9 | this.checkAuth();
10 | }
11 | componentWillReceiveProps(nextProps) {
12 | this.checkAuth();
13 | }
14 | checkAuth() {
15 | if(type === 'auth') {
16 | if (!this.props.isAuthorized) {
17 | this.props.router.push('/');
18 | }
19 | } else {
20 | if (this.props.isAuthorized) {
21 | this.props.router.push('/');
22 | }
23 | }
24 | }
25 | render() {
26 | return (
27 |
28 | {
29 | (type === 'auth') ?
30 | this.props.isAuthorized === true ? : null
31 | : this.props.isAuthorized === false ? : null
32 | }
33 |
34 | )
35 | }
36 | };
37 |
38 | const mapStateToProps = (state) => ({
39 | isAuthorized: state.getIn(['user', 'isAuthorized']),
40 | });
41 |
42 | return connect(mapStateToProps)(withRouter(AuthenticatedComponent));
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/Ch09/react-router-redux-github-finder/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-router-redux-github-finder",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "webpack.config.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --colors --inline --content-base ."
8 | },
9 | "author": "kdchang",
10 | "license": "MIT",
11 | "dependencies": {
12 | "immutable": "^3.8.1",
13 | "material-ui": "^0.15.4",
14 | "react": "^15.3.0",
15 | "react-dom": "^15.3.0",
16 | "react-redux": "^4.4.5",
17 | "react-router": "^2.6.1",
18 | "react-tap-event-plugin": "^1.0.0",
19 | "redux": "^3.5.2",
20 | "redux-actions": "^0.10.1",
21 | "redux-immutable": "^3.0.7",
22 | "redux-thunk": "^2.1.0",
23 | "whatwg-fetch": "^1.0.0"
24 | },
25 | "devDependencies": {
26 | "babel-core": "^6.13.2",
27 | "babel-eslint": "^6.1.2",
28 | "babel-loader": "^6.2.4",
29 | "babel-preset-es2015": "^6.13.2",
30 | "babel-preset-react": "^6.11.1",
31 | "babel-preset-stage-1": "^6.13.0",
32 | "eslint": "^3.3.0",
33 | "eslint-config-airbnb": "^10.0.1",
34 | "eslint-loader": "^1.5.0",
35 | "eslint-plugin-import": "^1.13.0",
36 | "eslint-plugin-jsx-a11y": "^2.1.0",
37 | "eslint-plugin-react": "^6.1.0",
38 | "html-webpack-plugin": "^2.22.0",
39 | "redux-logger": "^2.6.1",
40 | "webpack": "^1.13.1",
41 | "webpack-dev-server": "^1.14.1"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Appendix03/react-redux-test-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-redux-example",
3 | "version": "1.0.0",
4 | "description": "react-redux-example",
5 | "main": "webpack.config.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --colors --inline --content-base .",
8 | "test": "mocha --compilers js:babel-core/register"
9 | },
10 | "author": "kdchang",
11 | "license": "MIT",
12 | "dependencies": {
13 | "immutable": "^3.8.1",
14 | "react": "^15.3.0",
15 | "react-dom": "^15.3.0",
16 | "react-redux": "^4.4.5",
17 | "redux": "^3.5.2",
18 | "redux-actions": "^0.10.1",
19 | "redux-immutable": "^3.0.7",
20 | "uuid": "^2.0.2"
21 | },
22 | "devDependencies": {
23 | "babel-core": "^6.13.2",
24 | "babel-eslint": "^6.1.2",
25 | "babel-loader": "^6.2.4",
26 | "babel-preset-es2015": "^6.14.0",
27 | "babel-preset-react": "^6.11.1",
28 | "chai": "^3.5.0",
29 | "enzyme": "^2.4.1",
30 | "eslint": "^3.3.1",
31 | "eslint-config-airbnb": "^10.0.1",
32 | "eslint-loader": "^1.5.0",
33 | "eslint-plugin-import": "^1.13.0",
34 | "eslint-plugin-jsx-a11y": "^2.1.0",
35 | "eslint-plugin-react": "^6.1.1",
36 | "html-webpack-plugin": "^2.22.0",
37 | "jsdom": "^9.5.0",
38 | "mocha": "^3.0.2",
39 | "react-addons-test-utils": "^15.3.1",
40 | "redux-logger": "^2.6.1",
41 | "redux-mock-store": "^1.2.0",
42 | "webpack": "^1.13.1",
43 | "webpack-dev-server": "^1.14.1"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Ch03/todo-examples/app/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import TodoHeader from './components/TodoHeader';
4 | import TodoList from './components/TodoList';
5 |
6 | class App extends React.Component {
7 | constructor(props) {
8 | super(props);
9 | this.handleTodoTextChange = this.handleTodoTextChange.bind(this);
10 | this.handleAddTodo = this.handleAddTodo.bind(this);
11 | this.state = {
12 | todos: [],
13 | todo: {
14 | id: '',
15 | title: '',
16 | updatedAt: '',
17 | },
18 | };
19 | }
20 | handleTodoTextChange(e) {
21 | this.setState({
22 | todo: {
23 | title: e.target.value,
24 | },
25 | });
26 | console.log(e.target.value);
27 | }
28 | handleAddTodo() {
29 | this.state.todos.push(this.state.todo);
30 | this.setState({
31 | todos: this.state.todos,
32 | todo: {
33 | id: '',
34 | title: '',
35 | updatedAt: '',
36 | },
37 | });
38 | console.log(this.state.todo);
39 | }
40 | render() {
41 | return (
42 |
43 |
48 |
51 |
52 | );
53 | }
54 | }
55 |
56 | ReactDOM.render(, document.getElementById('app'));
57 |
--------------------------------------------------------------------------------
/Appendix02/ReactNativeFirebaseMotto/src/components/InputModal/InputModal.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactNative from 'react-native';
3 | import styles from './inputModelStyles';
4 | const { View, Text, Modal, TextInput, TouchableHighlight } = ReactNative;
5 | const InputModal = (props) => (
6 |
7 |
13 |
14 |
15 | Please Keyin your Motto!
16 |
19 |
20 |
24 |
27 | Cancel
28 |
29 |
30 |
34 |
37 | Submit
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | );
46 |
47 | export default InputModal;
--------------------------------------------------------------------------------
/Ch10/react-router-redux-node-isomorphic-open-cook/src/common/containers/RecipeBoxContainer/RecipeBoxContainer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { connect } from 'react-redux';
3 | import RecipeBox from '../../components/RecipeBox';
4 | import { browserHistory } from 'react-router';
5 |
6 | import {
7 | deleteRecipe,
8 | setRecipe,
9 | setUi
10 | } from '../../actions';
11 |
12 | export default connect(
13 | (state) => ({
14 | isAuthorized: state.getIn(['user', 'isAuthorized']),
15 | recipes: state.getIn(['recipe', 'recipes']),
16 | }),
17 | (dispatch) => ({
18 | onDeleteRecipe: (recipeId) => () => (
19 | dispatch(deleteRecipe(dispatch, recipeId))
20 | ),
21 | onUpadateRecipe: (recipes) => (recipeId) => () => {
22 | const recipeIndex = recipes.findIndex((_recipe) => (_recipe.get('_id') === recipeId));
23 | const recipe = recipeIndex !== -1 ? recipes.get(recipeIndex) : undefined;
24 | dispatch(setRecipe({ keyPath: ['recipe'], value: recipe }));
25 | dispatch(setRecipe({ keyPath: ['recipe', 'id'], value: recipeId }));
26 | dispatch(setUi({ key: 'isEdit', value: true }));
27 | browserHistory.push('/share?recipeId=' + recipeId);
28 | },
29 | }),
30 | (stateProps, dispatchProps, ownProps) => {
31 | const { recipes } = stateProps;
32 | const { onUpadateRecipe } = dispatchProps;
33 | return Object.assign({}, stateProps, dispatchProps, ownProps, {
34 | onUpadateRecipe: onUpadateRecipe(recipes),
35 | });
36 | }
37 | )(RecipeBox);
38 |
39 |
--------------------------------------------------------------------------------
/Ch10/react-redux-server-rendering/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-redux-server-rendering",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "node server/index.js"
8 | },
9 | "author": "kdchang",
10 | "license": "MIT",
11 | "dependencies": {
12 | "babel-polyfill": "^6.13.0",
13 | "babel-register": "^6.11.6",
14 | "body-parser": "^1.15.2",
15 | "express": "^4.14.0",
16 | "immutable": "^3.8.1",
17 | "morgan": "^1.7.0",
18 | "qs": "^6.2.1",
19 | "react": "^15.3.0",
20 | "react-dom": "^15.3.0",
21 | "react-redux": "^4.4.5",
22 | "react-router": "^2.6.1",
23 | "redux": "^3.5.2",
24 | "redux-actions": "^0.10.1",
25 | "redux-immutable": "^3.0.6",
26 | "redux-logger": "^2.6.1",
27 | "redux-thunk": "^2.1.0"
28 | },
29 | "devDependencies": {
30 | "babel-core": "^6.13.2",
31 | "babel-eslint": "^6.1.2",
32 | "babel-loader": "^6.2.4",
33 | "babel-preset-es2015": "^6.13.2",
34 | "babel-preset-react": "^6.11.1",
35 | "babel-preset-react-hmre": "^1.1.1",
36 | "babel-runtime": "^6.11.6",
37 | "eslint": "^3.2.2",
38 | "eslint-config-airbnb": "^10.0.0",
39 | "eslint-loader": "^1.5.0",
40 | "eslint-plugin-import": "^1.12.0",
41 | "eslint-plugin-jsx-a11y": "^2.0.1",
42 | "eslint-plugin-react": "^6.0.0",
43 | "webpack": "^1.13.1",
44 | "webpack-dev-middleware": "^1.6.1",
45 | "webpack-dev-server": "^1.14.1",
46 | "webpack-hot-middleware": "^2.12.2"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Appendix02/HelloWorldApp/ios/HelloWorldApp/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import "AppDelegate.h"
11 |
12 | #import "RCTBundleURLProvider.h"
13 | #import "RCTRootView.h"
14 |
15 | @implementation AppDelegate
16 |
17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
18 | {
19 | NSURL *jsCodeLocation;
20 |
21 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
22 |
23 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
24 | moduleName:@"HelloWorldApp"
25 | initialProperties:nil
26 | launchOptions:launchOptions];
27 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
28 |
29 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
30 | UIViewController *rootViewController = [UIViewController new];
31 | rootViewController.view = rootView;
32 | self.window.rootViewController = rootViewController;
33 | [self.window makeKeyAndVisible];
34 | return YES;
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------