├── .eslintrc
├── .gitignore
├── README.md
├── ep01-setup
├── README.md
├── app
│ ├── components
│ │ └── App.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep02-submit-input-field
├── README.md
├── app
│ ├── components
│ │ └── App.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep03-handle-onchange
├── README.md
├── app
│ ├── components
│ │ └── App.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep04-add-to-collection
├── README.md
├── app
│ ├── components
│ │ └── App.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep05-displaylist-component
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep06-delete-todo
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep07-mark-as-done
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep08-displayitem-component
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep09-display-count
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep10-switch-to-todo-part1
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep11-switch-to-todo-part2
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep12-make-done-really-work
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep13-clear-completed
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep14-add-id-to-todo
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep15-use-proptypes
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep16-new-css
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep17-edit-todo-part1
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep18-edit-todo-part2
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ └── stylesheets
│ │ └── main.css
├── package.json
└── webpack.config.js
├── ep19-call-api-jquery
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep20-using-fetch
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep21-general-refactoring
├── README.md
├── app
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep22-building-todoactions
├── README.md
├── app
│ ├── actions
│ │ └── TodoActions.js
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep23-building-todostore
├── README.md
├── app
│ ├── actions
│ │ └── TodoActions.js
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ ├── stores
│ │ └── TodoStore.js
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep24-delete-todo-using-flux
├── README.md
├── app
│ ├── actions
│ │ └── TodoActions.js
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ ├── stores
│ │ └── TodoStore.js
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep25-add-todo-using-flux
├── README.md
├── app
│ ├── actions
│ │ └── TodoActions.js
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ ├── stores
│ │ └── TodoStore.js
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep26-enhance-todo-store
├── README.md
├── app
│ ├── actions
│ │ └── TodoActions.js
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── main.jsx
│ ├── stores
│ │ └── TodoStore.js
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep27-use-dispatcher
├── README.md
├── app
│ ├── actions
│ │ └── TodoActions.js
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── dispatcher
│ │ └── AppDispatcher.js
│ ├── main.jsx
│ ├── stores
│ │ └── TodoStore.js
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep28-more-dispatcher-usage
├── README.md
├── app
│ ├── actions
│ │ └── TodoActions.js
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── dispatcher
│ │ └── AppDispatcher.js
│ ├── main.jsx
│ ├── stores
│ │ └── TodoStore.js
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep29-emit
├── README.md
├── app
│ ├── actions
│ │ └── TodoActions.js
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ └── DisplayList.jsx
│ ├── dispatcher
│ │ └── AppDispatcher.js
│ ├── main.jsx
│ ├── stores
│ │ └── TodoStore.js
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
├── ep30-extract-form-into-componenet-from-app
├── README.md
├── app
│ ├── actions
│ │ └── TodoActions.js
│ ├── components
│ │ ├── App.jsx
│ │ ├── DisplayItem.jsx
│ │ ├── DisplayList.jsx
│ │ └── TodoForm.jsx
│ ├── dispatcher
│ │ └── AppDispatcher.js
│ ├── main.jsx
│ ├── stores
│ │ └── TodoStore.js
│ ├── stylesheets
│ │ └── main.css
│ └── utils
│ │ ├── api.js
│ │ └── constants.js
├── package.json
└── webpack.config.js
└── ep31-get-all-todos
├── README.md
├── app
├── actions
│ └── TodoActions.js
├── components
│ ├── App.jsx
│ ├── DisplayItem.jsx
│ ├── DisplayList.jsx
│ └── TodoForm.jsx
├── dispatcher
│ └── AppDispatcher.js
├── main.jsx
├── stores
│ └── TodoStore.js
├── stylesheets
│ └── main.css
└── utils
│ ├── api.js
│ └── constants.js
├── package.json
└── webpack.config.js
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "env": {
4 | "browser": true,
5 | "es6": true,
6 | "node": true,
7 | "jquery": true // This will remove warnings related to $ being undefined. PR #97
8 | },
9 | "plugins": [
10 | "react" // This will remove warnings related to React not being defined. PR #98
11 | ],
12 | "ecmaFeatures": {
13 | "arrowFunctions": true,
14 | "blockBindings": true,
15 | "classes": true,
16 | "defaultParams": true,
17 | "destructuring": true,
18 | "forOf": true,
19 | "generators": true,
20 | "modules": true,
21 | "spread": true,
22 | "templateStrings": true,
23 | "jsx": true
24 | },
25 | "rules": {
26 | "consistent-return": [0],
27 | "key-spacing": [0],
28 | "quotes": [0],
29 | "new-cap": [0],
30 | "no-multi-spaces": [0],
31 | "no-shadow": [0],
32 |
33 | // allow alert
34 | "no-alert": [0],
35 |
36 | // in ReactJS it is common to have components defined first and then used later. PR #88
37 | "no-unused-vars": [0],
38 |
39 | //allow function names starting with underscore statements like this._executeQuery is being flagged. PR #86
40 | "no-underscore-dangle": [0],
41 |
42 | //In ReactNavite code it is common to have styles.xxx at the top while styles is defined later. PR #85
43 | "no-use-before-define": [0, "nofunc"],
44 |
45 | // Allow dangling commas
46 | "comma-dangle": [0],
47 |
48 | // Force space after keywords like if, else and before code blocks. PR #91
49 | "space-after-keywords": [2],
50 | "space-before-blocks": [2],
51 |
52 | // Don't warn if camelcase variable names are used. PR #96
53 | "camelcase": [0],
54 |
55 | // Prefer === over ==. PR #100
56 | "eqeqeq": [2]
57 |
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | npm-debug.log
2 | **/node_modules/*
3 | build/*
4 | .idea
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # learn-reactjs-in-steps
2 |
3 | **These videos were created in 2015 and now they are out dated.**
4 |
5 | This is code repository for videos created as part of [Learn ReactJS in steps](http://bigbinary.com/videos/learn-reactjs-in-steps).
6 |
7 | In this application we start with a "Hello World" applillcation and we add features to the application to make a fully functional "TODO application".
8 |
--------------------------------------------------------------------------------
/ep01-setup/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [webpack docs](http://webpack.github.io/docs/)
13 | * [Source code](...)
14 |
--------------------------------------------------------------------------------
/ep01-setup/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class App extends React.Component {
4 | render () {
5 | return
Hello World
;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/ep01-setup/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep01-setup/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep01-setup/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep01-setup/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep02-submit-input-field/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Exploring ES6](http://exploringjs.com/es6/index.html)
13 | * [Source code](...)
14 |
--------------------------------------------------------------------------------
/ep02-submit-input-field/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class App extends React.Component {
4 |
5 | handleSubmit (event) {
6 | event.preventDefault();
7 | console.log("form was submitted");
8 |
9 | }
10 |
11 | render () {
12 | return ;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ep02-submit-input-field/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep02-submit-input-field/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep02-submit-input-field/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep02-submit-input-field/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep03-handle-onchange/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep03-handle-onchange/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class App extends React.Component {
4 |
5 | constructor () {
6 | super();
7 | this.state = { text: '' };
8 | }
9 |
10 | handleSubmit (event) {
11 | event.preventDefault();
12 | console.log("form was submitted");
13 | var text = this.state.text;
14 | console.log("submitted form has value ", text);
15 | this.setState({ text: '' });
16 | }
17 |
18 | handleChange (event) {
19 | var text = event.target.value;
20 | console.log(text);
21 | this.setState({ text: text });
22 | }
23 |
24 | render () {
25 | return ;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ep03-handle-onchange/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep03-handle-onchange/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep03-handle-onchange/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep03-handle-onchange/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep04-add-to-collection/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep04-add-to-collection/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class App extends React.Component {
4 |
5 | constructor () {
6 | super();
7 | this.state = { text: '', items: [] };
8 | }
9 |
10 | handleSubmit (event) {
11 | event.preventDefault();
12 | console.log("form was submitted");
13 |
14 | var text = this.state.text;
15 | var newItems = this.state.items.concat(text);
16 |
17 | console.log("submitted form has value ", text);
18 | this.setState({ text: '', items: newItems });
19 | }
20 |
21 | handleChange (event) {
22 | var text = event.target.value;
23 | console.log(text);
24 | this.setState({ text: text });
25 | }
26 |
27 | render () {
28 | return
29 |
TODO
30 |
34 |
35 |
36 | { this.state.items.toString() }
37 |
38 |
;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/ep04-add-to-collection/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep04-add-to-collection/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep04-add-to-collection/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep04-add-to-collection/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep05-displaylist-component/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep05-displaylist-component/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayList from './DisplayList';
3 |
4 | export default class App extends React.Component {
5 |
6 | constructor () {
7 | super();
8 | this.state = { text: '', items: [] };
9 | }
10 |
11 | handleSubmit (event) {
12 | event.preventDefault();
13 | console.log("form was submitted");
14 |
15 | var text = this.state.text;
16 | var newItems = this.state.items.concat(text);
17 |
18 | console.log("submitted form has value ", text);
19 | this.setState({ text: '', items: newItems });
20 | }
21 |
22 | handleChange (event) {
23 | var text = event.target.value;
24 | console.log(text);
25 | this.setState({ text: text });
26 | }
27 |
28 | render () {
29 | return
30 |
TODO
31 |
35 |
36 |
37 |
;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ep05-displaylist-component/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayList extends React.Component {
4 |
5 | render () {
6 | return
7 | { this.props.items.map((item, i) => {
8 | return - { item }
;
9 | }) }
10 |
;
11 | }
12 |
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/ep05-displaylist-component/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep05-displaylist-component/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep05-displaylist-component/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep05-displaylist-component/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep06-delete-todo/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep06-delete-todo/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayList from './DisplayList';
3 |
4 | export default class App extends React.Component {
5 |
6 | constructor () {
7 | super();
8 | this.state = { text: '', items: [] };
9 | }
10 |
11 | handleDelete (itemToBeDeleted) {
12 | console.log(itemToBeDeleted);
13 | var newItems = this.state.items.filter( (_item) => {
14 | return _item != itemToBeDeleted
15 | } )
16 |
17 | this.setState({ items: newItems });
18 | }
19 |
20 | handleSubmit (event) {
21 | event.preventDefault();
22 | console.log("form was submitted");
23 |
24 | var text = this.state.text;
25 | var newItems = this.state.items.concat(text);
26 |
27 | console.log("submitted form has value ", text);
28 | this.setState({ text: '', items: newItems });
29 | }
30 |
31 | handleChange (event) {
32 | var text = event.target.value;
33 | console.log(text);
34 | this.setState({ text: text });
35 | }
36 |
37 | render () {
38 | return
39 |
TODO
40 |
44 |
45 |
48 |
;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/ep06-delete-todo/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayList extends React.Component {
4 |
5 | render () {
6 | return
7 | { this.props.items.map((item, i) => {
8 | return -
9 | { item }
10 |
11 | [x]
12 |
13 |
;
14 | }) }
15 |
;
16 | }
17 |
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/ep06-delete-todo/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep06-delete-todo/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep06-delete-todo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep06-delete-todo/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep07-mark-as-done/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep07-mark-as-done/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayList from './DisplayList';
3 |
4 | export default class App extends React.Component {
5 |
6 | constructor () {
7 | super();
8 | this.state = { text: '', items: ['eggs', 'banana', 'bread'] };
9 | }
10 |
11 | handleDelete (itemToBeDeleted) {
12 | console.log(itemToBeDeleted);
13 | var newItems = this.state.items.filter( (_item) => {
14 | return _item != itemToBeDeleted
15 | } )
16 |
17 | this.setState({ items: newItems });
18 | }
19 |
20 | handleSubmit (event) {
21 | event.preventDefault();
22 | console.log("form was submitted");
23 |
24 | var text = this.state.text;
25 | var newItems = this.state.items.concat(text);
26 |
27 | console.log("submitted form has value ", text);
28 | this.setState({ text: '', items: newItems });
29 | }
30 |
31 | handleChange (event) {
32 | var text = event.target.value;
33 | console.log(text);
34 | this.setState({ text: text });
35 | }
36 |
37 | render () {
38 | return
39 |
TODO
40 |
44 |
45 |
48 |
;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/ep07-mark-as-done/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayList extends React.Component {
4 |
5 | constructor () {
6 | super();
7 | this.state = { done: false };
8 | }
9 |
10 | handleOnChange (event) {
11 | var _done = !this.state.done;
12 | this.setState({ done: _done });
13 | }
14 |
15 | render () {
16 | return ;
32 | }
33 |
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/ep07-mark-as-done/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep07-mark-as-done/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep07-mark-as-done/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep07-mark-as-done/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep08-displayitem-component/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep08-displayitem-component/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayList from './DisplayList';
3 |
4 | export default class App extends React.Component {
5 |
6 | constructor () {
7 | super();
8 | this.state = { text: '', items: ['eggs', 'banana', 'bread'] };
9 | }
10 |
11 | handleDelete (itemToBeDeleted) {
12 | console.log(itemToBeDeleted);
13 | var newItems = this.state.items.filter( (_item) => {
14 | return _item != itemToBeDeleted
15 | } )
16 |
17 | this.setState({ items: newItems });
18 | }
19 |
20 | handleSubmit (event) {
21 | event.preventDefault();
22 | console.log("form was submitted");
23 |
24 | var text = this.state.text;
25 | var newItems = this.state.items.concat(text);
26 |
27 | console.log("submitted form has value ", text);
28 | this.setState({ text: '', items: newItems });
29 | }
30 |
31 | handleChange (event) {
32 | var text = event.target.value;
33 | console.log(text);
34 | this.setState({ text: text });
35 | }
36 |
37 | render () {
38 | return
39 |
TODO
40 |
44 |
45 |
48 |
;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/ep08-displayitem-component/app/components/DisplayItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayItem extends React.Component {
4 |
5 | constructor () {
6 | super();
7 | this.state = { done: false };
8 | }
9 |
10 | handleOnChange (event) {
11 | var _done = !this.state.done;
12 | this.setState({ done: _done });
13 | }
14 |
15 | render () {
16 | var item = this.props.item;
17 |
18 | return
19 |
24 |
25 | { item }
26 |
27 | [x]
28 |
29 | ;
30 | }
31 |
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/ep08-displayitem-component/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.items.map((item, i) => {
9 | return ;
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/ep08-displayitem-component/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep08-displayitem-component/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep08-displayitem-component/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep08-displayitem-component/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep09-display-count/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep09-display-count/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayList from './DisplayList';
3 |
4 | export default class App extends React.Component {
5 |
6 | constructor () {
7 | super();
8 | this.state = { text: '', items: ['eggs', 'banana', 'bread'] };
9 | }
10 |
11 | handleDelete (itemToBeDeleted) {
12 | console.log(itemToBeDeleted);
13 | var newItems = this.state.items.filter( (_item) => {
14 | return _item != itemToBeDeleted
15 | } )
16 |
17 | this.setState({ items: newItems });
18 | }
19 |
20 | handleSubmit (event) {
21 | event.preventDefault();
22 | console.log("form was submitted");
23 |
24 | var text = this.state.text;
25 | var newItems = this.state.items.concat(text);
26 |
27 | console.log("submitted form has value ", text);
28 | this.setState({ text: '', items: newItems });
29 | }
30 |
31 | handleChange (event) {
32 | var text = event.target.value;
33 | console.log(text);
34 | this.setState({ text: text });
35 | }
36 |
37 | render () {
38 | return
39 |
TODO
40 |
44 |
45 |
46 | Number of total tasks: { this.state.items.length }
47 |
48 |
49 | Number of total tasks done: { this.state.items.filter((item) => { item.done }).length }
50 |
51 |
52 |
55 |
;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/ep09-display-count/app/components/DisplayItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayItem extends React.Component {
4 |
5 | constructor () {
6 | super();
7 | this.state = { done: false };
8 | }
9 |
10 | handleDone (event) {
11 | var _done = !this.state.done;
12 | this.setState({ done: _done });
13 | }
14 |
15 | render () {
16 | var item = this.props.item;
17 |
18 | return
19 |
24 |
25 | { item }
26 |
27 | [x]
28 |
29 | ;
30 | }
31 |
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/ep09-display-count/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.items.map((item, i) => {
9 | return ;
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/ep09-display-count/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep09-display-count/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep09-display-count/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep09-display-count/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep10-switch-to-todo-part1/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep10-switch-to-todo-part1/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayList from './DisplayList';
3 |
4 | export default class App extends React.Component {
5 |
6 | constructor () {
7 | super();
8 | this.state = { title: '', todos: ['eggs', 'banana', 'bread'] };
9 | }
10 |
11 | handleDelete (titleToBeDeleted) {
12 | var newTodos = this.state.todos.filter( (_title) => {
13 | return _title != titleToBeDeleted
14 | } )
15 |
16 | this.setState({ todos: newTodos});
17 | }
18 |
19 | handleSubmit (event) {
20 | event.preventDefault();
21 |
22 | var title = this.state.title;
23 | var newTodos = this.state.todos.concat(title);
24 |
25 | this.setState({ title: '', todos: newTodos });
26 | }
27 |
28 | handleChange (event) {
29 | var title = event.target.value;
30 | this.setState({ title: title });
31 | }
32 |
33 | render () {
34 | return
35 |
TODO
36 |
40 |
41 |
42 | Number of total tasks: { this.state.todos.length }
43 |
44 |
45 | Number of total tasks done: { this.state.todos.filter((title) => { title.done }).length }
46 |
47 |
48 |
51 |
;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ep10-switch-to-todo-part1/app/components/DisplayItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayItem extends React.Component {
4 |
5 | constructor () {
6 | super();
7 | this.state = { done: false };
8 | }
9 |
10 | handleDone (event) {
11 | var _done = !this.state.done;
12 | this.setState({ done: _done });
13 | }
14 |
15 | render () {
16 | var title = this.props.title;
17 |
18 | return
19 |
24 |
25 | { title }
26 |
27 | [x]
28 |
29 | ;
30 | }
31 |
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/ep10-switch-to-todo-part1/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((title, i) => {
9 | return ;
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/ep10-switch-to-todo-part1/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep10-switch-to-todo-part1/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep10-switch-to-todo-part1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep10-switch-to-todo-part1/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep11-switch-to-todo-part2/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep11-switch-to-todo-part2/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayList from './DisplayList';
3 |
4 | export default class App extends React.Component {
5 |
6 | constructor () {
7 | super();
8 | this.state = { title: '', todos: [
9 | { title: 'eggs', done: false },
10 | { title: 'banana', done: false },
11 | { title: 'bread', done: false }
12 | ] };
13 | }
14 |
15 | handleDelete (titleToBeDeleted) {
16 | var newTodos = this.state.todos.filter( (todo) => {
17 | return todo.title != titleToBeDeleted
18 | } )
19 |
20 | this.setState({ todos: newTodos});
21 | }
22 |
23 | handleSubmit (event) {
24 | event.preventDefault();
25 |
26 | var title = this.state.title;
27 | var newTodos = this.state.todos.concat({ title: title, done: false });
28 |
29 | this.setState({ title: '', todos: newTodos });
30 | }
31 |
32 | handleChange (event) {
33 | var title = event.target.value;
34 | this.setState({ title: title });
35 | }
36 |
37 | render () {
38 | return
39 |
TODO
40 |
44 |
45 |
46 | Number of total tasks: { this.state.todos.length }
47 |
48 |
49 | Number of total tasks done: { this.state.todos.filter((todo) => { todo.done }).length }
50 |
51 |
52 |
55 |
;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/ep11-switch-to-todo-part2/app/components/DisplayItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayItem extends React.Component {
4 |
5 | constructor () {
6 | super();
7 | this.state = { done: false };
8 | }
9 |
10 | handleDone (event) {
11 | var _done = !this.state.done;
12 | this.setState({ done: _done });
13 | }
14 |
15 | render () {
16 | var title = this.props.title;
17 |
18 | return
19 |
24 |
25 | { title }
26 |
27 | [x]
28 |
29 | ;
30 | }
31 |
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/ep11-switch-to-todo-part2/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return ;
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/ep11-switch-to-todo-part2/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep11-switch-to-todo-part2/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep11-switch-to-todo-part2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep11-switch-to-todo-part2/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep12-make-done-really-work/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep12-make-done-really-work/app/components/DisplayItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayItem extends React.Component {
4 |
5 | render () {
6 | var todo = this.props.todo;
7 | var title = todo.title;
8 |
9 | return
10 |
15 |
16 | { title }
17 |
18 | [x]
19 |
20 | ;
21 | }
22 |
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/ep12-make-done-really-work/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return ;
14 | }) }
15 |
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/ep12-make-done-really-work/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep12-make-done-really-work/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep12-make-done-really-work/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep12-make-done-really-work/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep13-clear-completed/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Source code](...)
13 |
--------------------------------------------------------------------------------
/ep13-clear-completed/app/components/DisplayItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayItem extends React.Component {
4 |
5 | render () {
6 | var todo = this.props.todo;
7 | var title = todo.title;
8 |
9 | return
10 |
15 |
16 | { title }
17 |
18 | [x]
19 |
20 | ;
21 | }
22 |
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/ep13-clear-completed/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return ;
14 | }) }
15 |
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/ep13-clear-completed/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep13-clear-completed/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep13-clear-completed/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "react": "^0.13.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ep13-clear-completed/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep14-add-id-to-todo/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * `npm install random-key --save`
13 | * [Source code](...)
14 |
--------------------------------------------------------------------------------
/ep14-add-id-to-todo/app/components/DisplayItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayItem extends React.Component {
4 |
5 | render () {
6 | var todo = this.props.todo;
7 |
8 | return
9 |
14 |
15 | { todo.title }
16 |
17 | [x]
18 |
19 | ;
20 | }
21 |
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/ep14-add-id-to-todo/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return ;
14 | }) }
15 |
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/ep14-add-id-to-todo/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep14-add-id-to-todo/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep14-add-id-to-todo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "random-key": "^0.3.2",
27 | "react": "^0.13.3"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ep14-add-id-to-todo/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep15-use-proptypes/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * `npm install random-key --save`
13 | * [Source code](...)
14 |
--------------------------------------------------------------------------------
/ep15-use-proptypes/app/components/DisplayItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayItem extends React.Component {
4 |
5 | render () {
6 | var todo = this.props.todo;
7 |
8 | return
9 |
14 |
15 | { todo.title }
16 |
17 | [x]
18 |
19 | ;
20 | }
21 |
22 | }
23 |
24 | DisplayItem.propTypes = {
25 | todo: React.PropTypes.object.isRequired,
26 | handleDone: React.PropTypes.func.isRequired,
27 | handleDelete: React.PropTypes.func.isRequired
28 | }
29 |
--------------------------------------------------------------------------------
/ep15-use-proptypes/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return ;
14 | }) }
15 |
16 | }
17 |
18 | }
19 |
20 | DisplayList.propTypes = {
21 | todos: React.PropTypes.array.isRequired,
22 | handleDone: React.PropTypes.func.isRequired,
23 | handleDelete: React.PropTypes.func.isRequired
24 | }
25 |
--------------------------------------------------------------------------------
/ep15-use-proptypes/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var app = document.createElement('div');
10 | document.body.appendChild(app);
11 |
12 | React.render(, app);
13 | }
14 |
--------------------------------------------------------------------------------
/ep15-use-proptypes/app/stylesheets/main.css:
--------------------------------------------------------------------------------
1 | body{
2 | font-size: 200%;
3 | }
4 |
--------------------------------------------------------------------------------
/ep15-use-proptypes/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "random-key": "^0.3.2",
27 | "react": "^0.13.3"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ep15-use-proptypes/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep16-new-css/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * `npm install random-key --save`
13 | * [Source code](...)
14 |
--------------------------------------------------------------------------------
/ep16-new-css/app/components/DisplayItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayItem extends React.Component {
4 |
5 | render () {
6 | var todo = this.props.todo;
7 |
8 | return
9 |
14 |
15 |
18 |
19 |
22 | [x]
23 |
24 | ;
25 | }
26 |
27 | }
28 |
29 | DisplayItem.propTypes = {
30 | todo: React.PropTypes.object.isRequired,
31 | handleDone: React.PropTypes.func.isRequired,
32 | handleDelete: React.PropTypes.func.isRequired
33 | }
34 |
--------------------------------------------------------------------------------
/ep16-new-css/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
15 | }) }
16 |
17 | }
18 |
19 | }
20 |
21 | DisplayList.propTypes = {
22 | todos: React.PropTypes.array.isRequired,
23 | handleDone: React.PropTypes.func.isRequired,
24 | handleDelete: React.PropTypes.func.isRequired
25 | }
26 |
--------------------------------------------------------------------------------
/ep16-new-css/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep16-new-css/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "random-key": "^0.3.2",
27 | "react": "^0.13.3"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ep16-new-css/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep17-edit-todo-part1/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * `npm install random-key --save`
13 | * [Source code](...)
14 |
--------------------------------------------------------------------------------
/ep17-edit-todo-part1/app/components/DisplayItem.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class DisplayItem extends React.Component {
4 |
5 | constructor () {
6 | super();
7 | this.state = { editing: false }
8 | }
9 |
10 | handleEditing (event) {
11 | this.setState({ editing: true });
12 | }
13 |
14 | handleEditingDone (event) {
15 | if (event.keyCode === 13 ) { // submit
16 | this.setState({ editing: false });
17 | }
18 | }
19 |
20 | render () {
21 | var todo = this.props.todo;
22 |
23 | var viewStyle = {};
24 | var editStyle = {};
25 |
26 | if (this.state.editing) {
27 | viewStyle.display = 'none';
28 | } else {
29 | editStyle.display = 'none';
30 | }
31 |
32 | return
33 |
34 |
39 |
40 |
43 |
44 |
47 | [x]
48 |
49 |
50 |
51 |
55 |
56 | }
57 |
58 | }
59 |
60 | DisplayItem.propTypes = {
61 | todo: React.PropTypes.object.isRequired,
62 | handleDone: React.PropTypes.func.isRequired,
63 | handleDelete: React.PropTypes.func.isRequired
64 | }
65 |
--------------------------------------------------------------------------------
/ep17-edit-todo-part1/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
15 | }) }
16 |
17 | }
18 |
19 | }
20 |
21 | DisplayList.propTypes = {
22 | todos: React.PropTypes.array.isRequired,
23 | handleDone: React.PropTypes.func.isRequired,
24 | handleDelete: React.PropTypes.func.isRequired
25 | }
26 |
--------------------------------------------------------------------------------
/ep17-edit-todo-part1/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep17-edit-todo-part1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "random-key": "^0.3.2",
27 | "react": "^0.13.3"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ep17-edit-todo-part1/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep18-edit-todo-part2/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * `npm install random-key --save`
13 | * [Source code](...)
14 |
--------------------------------------------------------------------------------
/ep18-edit-todo-part2/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
15 | }) }
16 |
17 | }
18 |
19 | }
20 |
21 | DisplayList.propTypes = {
22 | todos: React.PropTypes.array.isRequired,
23 | handleDone: React.PropTypes.func.isRequired,
24 | handleDelete: React.PropTypes.func.isRequired
25 | }
26 |
--------------------------------------------------------------------------------
/ep18-edit-todo-part2/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep18-edit-todo-part2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "random-key": "^0.3.2",
27 | "react": "^0.13.3"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ep18-edit-todo-part2/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep19-call-api-jquery/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * `npm install jquery --save`
13 |
--------------------------------------------------------------------------------
/ep19-call-api-jquery/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
15 | }) }
16 |
17 | }
18 |
19 | }
20 |
21 | DisplayList.propTypes = {
22 | todos: React.PropTypes.array.isRequired,
23 | handleDone: React.PropTypes.func.isRequired,
24 | handleDelete: React.PropTypes.func.isRequired
25 | }
26 |
--------------------------------------------------------------------------------
/ep19-call-api-jquery/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep19-call-api-jquery/app/utils/api.js:
--------------------------------------------------------------------------------
1 | var Constants = require("./constants");
2 | var $ = require('jquery');
3 |
4 | var api = {
5 | getTasks (processDataCallback) {
6 | var url = Constants.BASE_URL + 'todos';
7 | this.makeAjaxCall(url, 'GET', {}, processDataCallback)
8 | },
9 |
10 | addTask (todo, processDataCallback) {
11 | var url = Constants.BASE_URL + 'todos';
12 | this.makeAjaxCall(url, 'POST', todo, processDataCallback)
13 | },
14 |
15 | markTaskDone (todo, processDataCallback) {
16 | var url = Constants.BASE_URL + 'todos/' + todo.id;
17 | var params = { done: todo.done };
18 | this.makeAjaxCall(url, 'PUT', params, processDataCallback)
19 | },
20 |
21 | deleteTask (idToBeDeleted, processDataCallback) {
22 | var url = Constants.BASE_URL + 'todos/' + idToBeDeleted;
23 | this.makeAjaxCall(url, 'DELETE', {}, processDataCallback)
24 | },
25 |
26 | makeAjaxCall (url, type, params, processDataCallback) {
27 | $.ajax({
28 | type: type,
29 | url: url,
30 | data: {
31 | api_key: Constants.API_KEY,
32 | todo: params
33 | },
34 | dataType: 'json',
35 | success: function(data) {
36 | console.log(data);
37 | processDataCallback(data);
38 | },
39 | error: function() {
40 | console.log("An error has occurred");
41 | }
42 | });
43 | }
44 | };
45 |
46 | module.exports = api;
47 |
--------------------------------------------------------------------------------
/ep19-call-api-jquery/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep19-call-api-jquery/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "jquery": "1.11.3",
27 | "random-key": "^0.3.2",
28 | "react": "^0.13.3"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ep19-call-api-jquery/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep20-using-fetch/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * `npm install fetch --save`
13 |
--------------------------------------------------------------------------------
/ep20-using-fetch/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
15 | }) }
16 |
17 | }
18 |
19 | }
20 |
21 | DisplayList.propTypes = {
22 | todos: React.PropTypes.array.isRequired,
23 | handleDone: React.PropTypes.func.isRequired,
24 | handleDelete: React.PropTypes.func.isRequired
25 | }
26 |
--------------------------------------------------------------------------------
/ep20-using-fetch/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep20-using-fetch/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTasks () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json());
14 | },
15 |
16 | addTask (todo) {
17 | var url = this.generateUrlWithApiKey('todos');
18 | var options = {
19 | method: 'POST',
20 | headers: HEADER,
21 | body: JSON.stringify({todo: todo})
22 | };
23 | return fetch(url, options)
24 | .then((res) => res.json());
25 | },
26 |
27 | markTaskDone (todo) {
28 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
29 | var options = {
30 | method: 'PUT',
31 | headers: HEADER,
32 | body: JSON.stringify({done: todo.done})
33 | };
34 | return fetch(url, options)
35 | .then((res) => res.json());
36 | },
37 |
38 | deleteTask (idToBeDeleted, processDataCallback) {
39 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
40 | return fetch(url, { method: 'DELETE' })
41 | .then((res) => res.json());
42 | },
43 |
44 | };
45 |
46 | module.exports = api;
47 |
--------------------------------------------------------------------------------
/ep20-using-fetch/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep20-using-fetch/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "jquery": "1.11.3",
27 | "random-key": "^0.3.2",
28 | "react": "^0.13.3",
29 | "whatwg-fetch": "^0.9.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ep20-using-fetch/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep21-general-refactoring/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
--------------------------------------------------------------------------------
/ep21-general-refactoring/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
15 | }) }
16 |
17 | }
18 |
19 | }
20 |
21 | DisplayList.propTypes = {
22 | todos: React.PropTypes.array.isRequired,
23 | toggleDone: React.PropTypes.func.isRequired,
24 | handleDelete: React.PropTypes.func.isRequired
25 | }
26 |
--------------------------------------------------------------------------------
/ep21-general-refactoring/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep21-general-refactoring/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep21-general-refactoring/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep21-general-refactoring/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "jquery": "1.11.3",
27 | "random-key": "^0.3.2",
28 | "react": "^0.13.3",
29 | "whatwg-fetch": "^0.9.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ep21-general-refactoring/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep22-building-todoactions/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
--------------------------------------------------------------------------------
/ep22-building-todoactions/app/actions/TodoActions.js:
--------------------------------------------------------------------------------
1 | var api = require("../utils/api");
2 |
3 | var TodoActions = {
4 |
5 | markTodoDone: (todo) => {
6 | console.log("Marking TODO as done");
7 | api.markTodoDone(todo)
8 | .then( () => {
9 | console.log("marked TODO as done successfully");
10 | TodoActions.getAllTodos();
11 | })
12 | },
13 |
14 | markTodoUnDone: (todo) => {
15 | console.log("Marking TODO as undone");
16 | api.markTodoUnDone(todo)
17 | .then( () => {
18 | console.log("marked TODO as undone successfully");
19 | TodoActions.getAllTodos();
20 | })
21 | },
22 |
23 | getAllTodos: () => {
24 | api.getTodos()
25 | .then( (responseData) => {
26 | var todos = responseData.todos;
27 | console.log("new todos", todos);
28 | })
29 | }
30 |
31 | }
32 |
33 | module.exports = TodoActions;
34 |
--------------------------------------------------------------------------------
/ep22-building-todoactions/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
15 | }) }
16 |
17 | }
18 |
19 | }
20 |
21 | DisplayList.propTypes = {
22 | todos: React.PropTypes.array.isRequired,
23 | toggleDone: React.PropTypes.func.isRequired,
24 | handleDelete: React.PropTypes.func.isRequired
25 | }
26 |
--------------------------------------------------------------------------------
/ep22-building-todoactions/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep22-building-todoactions/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep22-building-todoactions/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep22-building-todoactions/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "jquery": "1.11.3",
27 | "random-key": "^0.3.2",
28 | "react": "^0.13.3",
29 | "whatwg-fetch": "^0.9.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ep22-building-todoactions/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep23-building-todostore/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
--------------------------------------------------------------------------------
/ep23-building-todostore/app/actions/TodoActions.js:
--------------------------------------------------------------------------------
1 | var api = require("../utils/api");
2 | var TodoStore = require("../stores/TodoStore");
3 |
4 | var TodoActions = {
5 |
6 | markTodoDone: (todo) => {
7 | console.log("Marking TODO as done");
8 | api.markTodoDone(todo)
9 | .then( () => {
10 | console.log("marked TODO as done successfully");
11 | TodoActions.getAllTodos();
12 | })
13 | },
14 |
15 | markTodoUnDone: (todo) => {
16 | console.log("Marking TODO as undone");
17 | api.markTodoUnDone(todo)
18 | .then( () => {
19 | console.log("marked TODO as undone successfully");
20 | TodoActions.getAllTodos();
21 | })
22 | },
23 |
24 | getAllTodos: () => {
25 | api.getTodos()
26 | .then( (responseData) => {
27 | var todos = responseData.todos;
28 | console.log("new todos", todos);
29 | TodoStore.setTodos(todos);
30 | })
31 | }
32 |
33 | }
34 |
35 | module.exports = TodoActions;
36 |
--------------------------------------------------------------------------------
/ep23-building-todostore/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
15 | }) }
16 |
17 | }
18 |
19 | }
20 |
21 | DisplayList.propTypes = {
22 | todos: React.PropTypes.array.isRequired,
23 | toggleDone: React.PropTypes.func.isRequired,
24 | handleDelete: React.PropTypes.func.isRequired
25 | }
26 |
--------------------------------------------------------------------------------
/ep23-building-todostore/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep23-building-todostore/app/stores/TodoStore.js:
--------------------------------------------------------------------------------
1 | var _todos = {};
2 | var _callback;
3 |
4 | var TodoStore = {
5 |
6 | setTodos: (todos) => {
7 | _todos = todos;
8 | console.log("TodoStore", TodoStore.getTodos());
9 | _callback(todos);
10 | },
11 |
12 | getTodos: () => {
13 | return _todos;
14 | },
15 |
16 | addChangeListener: function (callback) {
17 | console.log("registering callback for changelistener");
18 | _callback = callback;
19 | }
20 | }
21 |
22 | module.exports = TodoStore;
23 |
--------------------------------------------------------------------------------
/ep23-building-todostore/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep23-building-todostore/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep23-building-todostore/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "jquery": "1.11.3",
27 | "random-key": "^0.3.2",
28 | "react": "^0.13.3",
29 | "whatwg-fetch": "^0.9.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ep23-building-todostore/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep24-delete-todo-using-flux/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
--------------------------------------------------------------------------------
/ep24-delete-todo-using-flux/app/actions/TodoActions.js:
--------------------------------------------------------------------------------
1 | var api = require("../utils/api");
2 | var TodoStore = require("../stores/TodoStore");
3 |
4 | var TodoActions = {
5 |
6 | deleteTodo: (todo) => {
7 | console.log("Deleting TODO");
8 | api.deleteTodo(todo.id)
9 | .then( () => {
10 | console.log("Deleted TODO successfully");
11 | TodoActions.getAllTodos();
12 | })
13 | },
14 |
15 | markTodoDone: (todo) => {
16 | console.log("Marking TODO as done");
17 | api.markTodoDone(todo)
18 | .then( () => {
19 | console.log("marked TODO as done successfully");
20 | TodoActions.getAllTodos();
21 | })
22 | },
23 |
24 | markTodoUnDone: (todo) => {
25 | console.log("Marking TODO as undone");
26 | api.markTodoUnDone(todo)
27 | .then( () => {
28 | console.log("marked TODO as undone successfully");
29 | TodoActions.getAllTodos();
30 | })
31 | },
32 |
33 | getAllTodos: () => {
34 | api.getTodos()
35 | .then( (responseData) => {
36 | var todos = responseData.todos;
37 | console.log("new todos", todos);
38 | TodoStore.setTodos(todos);
39 | })
40 | }
41 |
42 | }
43 |
44 | module.exports = TodoActions;
45 |
--------------------------------------------------------------------------------
/ep24-delete-todo-using-flux/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
19 | DisplayList.propTypes = {
20 | todos: React.PropTypes.array.isRequired
21 | }
22 |
--------------------------------------------------------------------------------
/ep24-delete-todo-using-flux/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep24-delete-todo-using-flux/app/stores/TodoStore.js:
--------------------------------------------------------------------------------
1 | var _todos = {};
2 | var _callback;
3 |
4 | var TodoStore = {
5 |
6 | setTodos: (todos) => {
7 | _todos = todos;
8 | console.log("TodoStore", TodoStore.getTodos());
9 | _callback(todos);
10 | },
11 |
12 | getTodos: () => {
13 | return _todos;
14 | },
15 |
16 | addChangeListener: function (callback) {
17 | console.log("registering callback for changelistener");
18 | _callback = callback;
19 | }
20 | }
21 |
22 | module.exports = TodoStore;
23 |
--------------------------------------------------------------------------------
/ep24-delete-todo-using-flux/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep24-delete-todo-using-flux/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep24-delete-todo-using-flux/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "jquery": "1.11.3",
27 | "random-key": "^0.3.2",
28 | "react": "^0.13.3",
29 | "whatwg-fetch": "^0.9.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ep24-delete-todo-using-flux/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep25-add-todo-using-flux/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
--------------------------------------------------------------------------------
/ep25-add-todo-using-flux/app/actions/TodoActions.js:
--------------------------------------------------------------------------------
1 | var api = require("../utils/api");
2 | var TodoStore = require("../stores/TodoStore");
3 |
4 | var TodoActions = {
5 |
6 | addTodo: (todo) => {
7 | console.log("adding TODO");
8 | api.addTodo(todo)
9 | .then( () => {
10 | console.log("Added TODO successfully");
11 | TodoActions.getAllTodos();
12 | })
13 | },
14 |
15 | deleteTodo: (todo) => {
16 | console.log("Deleting TODO");
17 | api.deleteTodo(todo.id)
18 | .then( () => {
19 | console.log("Deleted TODO successfully");
20 | TodoActions.getAllTodos();
21 | })
22 | },
23 |
24 | markTodoDone: (todo) => {
25 | console.log("Marking TODO as done");
26 | api.markTodoDone(todo)
27 | .then( () => {
28 | console.log("marked TODO as done successfully");
29 | TodoActions.getAllTodos();
30 | })
31 | },
32 |
33 | markTodoUnDone: (todo) => {
34 | console.log("Marking TODO as undone");
35 | api.markTodoUnDone(todo)
36 | .then( () => {
37 | console.log("marked TODO as undone successfully");
38 | TodoActions.getAllTodos();
39 | })
40 | },
41 |
42 | getAllTodos: () => {
43 | api.getTodos()
44 | .then( (responseData) => {
45 | var todos = responseData.todos;
46 | console.log("new todos", todos);
47 | TodoStore.setTodos(todos);
48 | })
49 | }
50 |
51 | }
52 |
53 | module.exports = TodoActions;
54 |
--------------------------------------------------------------------------------
/ep25-add-todo-using-flux/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
19 | DisplayList.propTypes = {
20 | todos: React.PropTypes.array.isRequired
21 | }
22 |
--------------------------------------------------------------------------------
/ep25-add-todo-using-flux/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep25-add-todo-using-flux/app/stores/TodoStore.js:
--------------------------------------------------------------------------------
1 | var _todos = {};
2 | var _callback;
3 |
4 | var TodoStore = {
5 |
6 | setTodos: (todos) => {
7 | _todos = todos;
8 | console.log("TodoStore", TodoStore.getTodos());
9 | _callback(todos);
10 | },
11 |
12 | getTodos: () => {
13 | return _todos;
14 | },
15 |
16 | addChangeListener: function (callback) {
17 | console.log("registering callback for changelistener");
18 | _callback = callback;
19 | }
20 | }
21 |
22 | module.exports = TodoStore;
23 |
--------------------------------------------------------------------------------
/ep25-add-todo-using-flux/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep25-add-todo-using-flux/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep25-add-todo-using-flux/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "jquery": "1.11.3",
27 | "random-key": "^0.3.2",
28 | "react": "^0.13.3",
29 | "whatwg-fetch": "^0.9.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ep25-add-todo-using-flux/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep26-enhance-todo-store/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
--------------------------------------------------------------------------------
/ep26-enhance-todo-store/app/actions/TodoActions.js:
--------------------------------------------------------------------------------
1 | var api = require("../utils/api");
2 | var TodoStore = require("../stores/TodoStore");
3 |
4 | var TodoActions = {
5 |
6 | addTodo: (todo) => {
7 | console.log("adding TODO");
8 | api.addTodo(todo)
9 | .then( () => {
10 | console.log("Added TODO successfully");
11 | TodoActions.getAllTodosAndUpdateStore();
12 | })
13 | },
14 |
15 | deleteTodo: (todo) => {
16 | console.log("Deleting TODO");
17 | api.deleteTodo(todo.id)
18 | .then( () => {
19 | console.log("Deleted TODO successfully");
20 | TodoStore.deleteTodo(todo);
21 | })
22 | },
23 |
24 | markTodoDone: (todo) => {
25 | console.log("Marking TODO as done");
26 | api.markTodoDone(todo)
27 | .then( () => {
28 | console.log("marked TODO as done successfully");
29 | TodoStore.markTodoDone(todo);
30 | })
31 | },
32 |
33 | markTodoUnDone: (todo) => {
34 | console.log("Marking TODO as undone");
35 | api.markTodoUnDone(todo)
36 | .then( () => {
37 | console.log("marked TODO as undone successfully");
38 | TodoStore.markTodoUnDone(todo);
39 | })
40 | },
41 |
42 | getAllTodosAndUpdateStore: () => {
43 | console.log("Performing getAllTodos");
44 | api.getTodos()
45 | .then( (responseData) => {
46 | var todos = responseData.todos;
47 | console.log("new todos", todos);
48 | TodoStore.setTodos(todos);
49 | })
50 | }
51 |
52 | }
53 |
54 | module.exports = TodoActions;
55 |
--------------------------------------------------------------------------------
/ep26-enhance-todo-store/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
19 | DisplayList.propTypes = {
20 | todos: React.PropTypes.array.isRequired
21 | }
22 |
--------------------------------------------------------------------------------
/ep26-enhance-todo-store/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep26-enhance-todo-store/app/stores/TodoStore.js:
--------------------------------------------------------------------------------
1 | var _todos = {};
2 | var _callback;
3 |
4 | var TodoStore = {
5 |
6 | deleteTodo: (todo) => {
7 | var newTodos = _todos.filter( (t) => {
8 | return t.id != todo.id
9 | } )
10 | _todos = newTodos;
11 | _callback(_todos);
12 | },
13 |
14 | markTodoDone: (todo) => {
15 | var _todo = _todos.filter((t) => {
16 | return t.id === todo.id;
17 | })[0];
18 |
19 | _todo.done = true;
20 | _callback(_todos);
21 | },
22 |
23 | markTodoUnDone: (todo) => {
24 | var _todo = _todos.filter((t) => {
25 | return t.id === todo.id;
26 | })[0];
27 |
28 | _todo.done = false;
29 | _callback(_todos);
30 | },
31 |
32 | setTodos: (todos) => {
33 | _todos = todos;
34 | console.log("TodoStore", TodoStore.getTodos());
35 | _callback(todos);
36 | },
37 |
38 | getTodos: () => {
39 | return _todos;
40 | },
41 |
42 | addChangeListener: function (callback) {
43 | console.log("registering callback for changelistener");
44 | _callback = callback;
45 | }
46 | }
47 |
48 | module.exports = TodoStore;
49 |
--------------------------------------------------------------------------------
/ep26-enhance-todo-store/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep26-enhance-todo-store/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep26-enhance-todo-store/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "jquery": "1.11.3",
27 | "random-key": "^0.3.2",
28 | "react": "^0.13.3",
29 | "whatwg-fetch": "^0.9.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ep26-enhance-todo-store/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep27-use-dispatcher/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
--------------------------------------------------------------------------------
/ep27-use-dispatcher/app/actions/TodoActions.js:
--------------------------------------------------------------------------------
1 | var api = require("../utils/api");
2 | var TodoStore = require("../stores/TodoStore");
3 | var AppDispatcher = require('../dispatcher/AppDispatcher');
4 |
5 | var TodoActions = {
6 |
7 | addTodo: (todo) => {
8 | console.log("adding TODO");
9 | api.addTodo(todo)
10 | .then( () => {
11 | console.log("Added TODO successfully");
12 | TodoActions.getAllTodosAndUpdateStore();
13 | })
14 | },
15 |
16 | deleteTodo: (todo) => {
17 | console.log("Deleting TODO");
18 | api.deleteTodo(todo.id)
19 | .then( () => {
20 | console.log("Deleted TODO successfully");
21 | TodoStore.deleteTodo(todo);
22 | })
23 | },
24 |
25 | markTodoDone: (todo) => {
26 | console.log("Marking TODO as done");
27 | api.markTodoDone(todo)
28 | .then( () => {
29 | console.log("marked TODO as done successfully");
30 | //TodoStore.markTodoDone(todo);
31 | AppDispatcher.dispatch({
32 | actionType: 'TODO_DONE',
33 | todo: todo
34 | });
35 |
36 | })
37 | },
38 |
39 | markTodoUnDone: (todo) => {
40 | console.log("Marking TODO as undone");
41 | api.markTodoUnDone(todo)
42 | .then( () => {
43 | console.log("marked TODO as undone successfully");
44 | TodoStore.markTodoUnDone(todo);
45 | })
46 | },
47 |
48 | getAllTodosAndUpdateStore: () => {
49 | console.log("Performing getAllTodos");
50 | api.getTodos()
51 | .then( (responseData) => {
52 | var todos = responseData.todos;
53 | console.log("new todos", todos);
54 | TodoStore.setTodos(todos);
55 | })
56 | }
57 |
58 | }
59 |
60 | module.exports = TodoActions;
61 |
--------------------------------------------------------------------------------
/ep27-use-dispatcher/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
19 | DisplayList.propTypes = {
20 | todos: React.PropTypes.array.isRequired
21 | }
22 |
--------------------------------------------------------------------------------
/ep27-use-dispatcher/app/dispatcher/AppDispatcher.js:
--------------------------------------------------------------------------------
1 | var Dispatcher = require('flux').Dispatcher;
2 |
3 | module.exports = new Dispatcher();
4 |
--------------------------------------------------------------------------------
/ep27-use-dispatcher/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep27-use-dispatcher/app/stores/TodoStore.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 |
3 | AppDispatcher.register(function(action) {
4 |
5 | switch(action.actionType) {
6 | case 'TODO_DONE':
7 | console.log("Handling TODO_DONE using dispatcher in store");
8 | TodoStore.markTodoDone(action.todo);
9 | break;
10 | }
11 |
12 | });
13 |
14 | var _todos = {};
15 | var _callback;
16 |
17 | var TodoStore = {
18 |
19 | deleteTodo: (todo) => {
20 | var newTodos = _todos.filter( (t) => {
21 | return t.id != todo.id
22 | } )
23 | _todos = newTodos;
24 | _callback(_todos);
25 | },
26 |
27 | markTodoDone: (todo) => {
28 | var _todo = _todos.filter((t) => {
29 | return t.id === todo.id;
30 | })[0];
31 |
32 | _todo.done = true;
33 | _callback(_todos);
34 | },
35 |
36 | markTodoUnDone: (todo) => {
37 | var _todo = _todos.filter((t) => {
38 | return t.id === todo.id;
39 | })[0];
40 |
41 | _todo.done = false;
42 | _callback(_todos);
43 | },
44 |
45 | setTodos: (todos) => {
46 | _todos = todos;
47 | console.log("TodoStore", TodoStore.getTodos());
48 | _callback(todos);
49 | },
50 |
51 | getTodos: () => {
52 | return _todos;
53 | },
54 |
55 | addChangeListener: function (callback) {
56 | console.log("registering callback for changelistener");
57 | _callback = callback;
58 | }
59 | }
60 |
61 | module.exports = TodoStore;
62 |
--------------------------------------------------------------------------------
/ep27-use-dispatcher/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep27-use-dispatcher/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep27-use-dispatcher/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "flux": "^2.1.1",
27 | "jquery": "1.11.3",
28 | "random-key": "^0.3.2",
29 | "react": "^0.13.3",
30 | "whatwg-fetch": "^0.9.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ep27-use-dispatcher/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep28-more-dispatcher-usage/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
--------------------------------------------------------------------------------
/ep28-more-dispatcher-usage/app/actions/TodoActions.js:
--------------------------------------------------------------------------------
1 | var api = require("../utils/api");
2 | var TodoStore = require("../stores/TodoStore");
3 | var AppDispatcher = require('../dispatcher/AppDispatcher');
4 | var Constants = require("../utils/constants");
5 |
6 | var TodoActions = {
7 |
8 | addTodo: (todo) => {
9 | api.addTodo(todo)
10 | .then( () => {
11 | TodoActions.getAllTodosAndUpdateStore();
12 | })
13 | },
14 |
15 | deleteTodo: (todo) => {
16 | api.deleteTodo(todo.id)
17 | .then( () => {
18 | AppDispatcher.dispatch({
19 | actionType: Constants.TODO_DELETE,
20 | todo: todo
21 | });
22 | })
23 | },
24 |
25 | markTodoDone: (todo) => {
26 | api.markTodoDone(todo)
27 | .then( () => {
28 | AppDispatcher.dispatch({
29 | actionType: Constants.TODO_DONE,
30 | todo: todo
31 | });
32 |
33 | })
34 | },
35 |
36 | markTodoUnDone: (todo) => {
37 | api.markTodoUnDone(todo)
38 | .then( () => {
39 | AppDispatcher.dispatch({
40 | actionType: Constants.TODO_UNDONE,
41 | todo: todo
42 | });
43 | })
44 | },
45 |
46 | getAllTodosAndUpdateStore: () => {
47 | api.getTodos()
48 | .then( (responseData) => {
49 | var todos = responseData.todos;
50 | TodoStore.setTodos(todos);
51 | AppDispatcher.dispatch({
52 | actionType: Constants.TODO_ADD
53 | });
54 | })
55 | }
56 |
57 | }
58 |
59 | module.exports = TodoActions;
60 |
--------------------------------------------------------------------------------
/ep28-more-dispatcher-usage/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
13 | })
14 | }
15 |
16 | }
17 |
18 | }
19 |
20 | DisplayList.propTypes = {
21 | todos: React.PropTypes.array.isRequired
22 | }
23 |
--------------------------------------------------------------------------------
/ep28-more-dispatcher-usage/app/dispatcher/AppDispatcher.js:
--------------------------------------------------------------------------------
1 | var Dispatcher = require('flux').Dispatcher;
2 |
3 | module.exports = new Dispatcher();
4 |
--------------------------------------------------------------------------------
/ep28-more-dispatcher-usage/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep28-more-dispatcher-usage/app/stores/TodoStore.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 | var Constants = require("../utils/constants");
3 |
4 | AppDispatcher.register(function(action) {
5 |
6 | switch(action.actionType) {
7 | case Constants.TODO_DONE:
8 | TodoStore.markTodoDone(action.todo);
9 | break;
10 |
11 | case Constants.TODO_UNDONE:
12 | TodoStore.markTodoUnDone(action.todo);
13 | break;
14 |
15 | case Constants.TODO_DELETE:
16 | TodoStore.deleteTodo(action.todo);
17 | break;
18 |
19 | case Constants.TODO_ADD:
20 | TodoStore.getTodos();
21 | break;
22 | }
23 |
24 | });
25 |
26 | var _todos = {};
27 | var _callback;
28 |
29 | var TodoStore = {
30 |
31 | deleteTodo: (todo) => {
32 | var newTodos = _todos.filter( (t) => {
33 | return t.id != todo.id
34 | } )
35 | _todos = newTodos;
36 | _callback(_todos);
37 | },
38 |
39 | markTodoDone: (todo) => {
40 | var _todo = _todos.filter((t) => {
41 | return t.id === todo.id;
42 | })[0];
43 |
44 | _todo.done = true;
45 | _callback(_todos);
46 | },
47 |
48 | markTodoUnDone: (todo) => {
49 | var _todo = _todos.filter((t) => {
50 | return t.id === todo.id;
51 | })[0];
52 |
53 | _todo.done = false;
54 | _callback(_todos);
55 | },
56 |
57 | setTodos: (todos) => {
58 | _todos = todos;
59 | console.log("TodoStore", TodoStore.getTodos());
60 | _callback(todos);
61 | },
62 |
63 | getTodos: () => {
64 | return _todos;
65 | _callback(todos);
66 | },
67 |
68 | addChangeListener: function (callback) {
69 | console.log("registering callback for changelistener");
70 | _callback = callback;
71 | }
72 | }
73 |
74 | module.exports = TodoStore;
75 |
--------------------------------------------------------------------------------
/ep28-more-dispatcher-usage/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep28-more-dispatcher-usage/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965",
4 | TODO_DONE: 'TODO_DONE',
5 | TODO_UNDONE: 'TODO_UNDONE',
6 | TODO_DELETE: 'TODO_DELETE',
7 | TODO_ADD: 'TODO_ADD'
8 | };
9 |
10 | module.exports = Constants;
11 |
--------------------------------------------------------------------------------
/ep28-more-dispatcher-usage/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "flux": "^2.1.1",
27 | "jquery": "1.11.3",
28 | "random-key": "^0.3.2",
29 | "react": "^0.13.3",
30 | "whatwg-fetch": "^0.9.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ep28-more-dispatcher-usage/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep29-emit/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
10 | #### Notes
11 |
12 | * [Nodejs Events](https://nodejs.org/api/events.html)
13 | * [object-assign](https://www.npmjs.com/package/object-assign)
14 | * `npm install --save object-assign`
15 |
--------------------------------------------------------------------------------
/ep29-emit/app/actions/TodoActions.js:
--------------------------------------------------------------------------------
1 | var api = require("../utils/api");
2 | var TodoStore = require("../stores/TodoStore");
3 | var AppDispatcher = require('../dispatcher/AppDispatcher');
4 |
5 | var TodoActions = {
6 |
7 | addTodo: (todo) => {
8 | console.log("adding TODO");
9 | api.addTodo(todo)
10 | .then( () => {
11 | api.getTodos()
12 | .then( (responseData) => {
13 | var todos = responseData.todos;
14 | console.log("All todos", todos);
15 | TodoStore.setTodos(todos);
16 | })
17 | })
18 | .then( () => {
19 | console.log("Added TODO successfully");
20 | AppDispatcher.dispatch({
21 | actionType: 'TODO_ADD'
22 | });
23 | })
24 | },
25 |
26 | deleteTodo: (todo) => {
27 | console.log("Deleting TODO");
28 | api.deleteTodo(todo.id)
29 | .then( () => {
30 | console.log("Deleted TODO successfully");
31 | AppDispatcher.dispatch({
32 | actionType: 'TODO_DELETE',
33 | todo: todo
34 | });
35 | })
36 | },
37 |
38 | markTodoDone: (todo) => {
39 | console.log("Marking TODO as done");
40 | api.markTodoDone(todo)
41 | .then( () => {
42 | console.log("marked TODO as done successfully");
43 | AppDispatcher.dispatch({
44 | actionType: 'TODO_DONE',
45 | todo: todo
46 | });
47 |
48 | })
49 | },
50 |
51 | markTodoUnDone: (todo) => {
52 | console.log("Marking TODO as undone");
53 | api.markTodoUnDone(todo)
54 | .then( () => {
55 | console.log("marked TODO as undone successfully");
56 | AppDispatcher.dispatch({
57 | actionType: 'TODO_UNDONE',
58 | todo: todo
59 | });
60 | })
61 | },
62 |
63 |
64 |
65 |
66 | }
67 |
68 | module.exports = TodoActions;
69 |
--------------------------------------------------------------------------------
/ep29-emit/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
19 | DisplayList.propTypes = {
20 | todos: React.PropTypes.array.isRequired
21 | }
22 |
--------------------------------------------------------------------------------
/ep29-emit/app/dispatcher/AppDispatcher.js:
--------------------------------------------------------------------------------
1 | var Dispatcher = require('flux').Dispatcher;
2 |
3 | module.exports = new Dispatcher();
4 |
--------------------------------------------------------------------------------
/ep29-emit/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep29-emit/app/stores/TodoStore.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 | var EventEmitter = require('events').EventEmitter;
3 | var assign = require('object-assign');
4 |
5 | AppDispatcher.register(function(action) {
6 |
7 | switch(action.actionType) {
8 | case 'TODO_DONE':
9 | console.log("Handling TODO_DONE using dispatcher in store");
10 | TodoStore.markTodoDone(action.todo);
11 | break;
12 |
13 | case 'TODO_UNDONE':
14 | console.log("Handling TODO_UNDONE using dispatcher in store");
15 | TodoStore.markTodoUnDone(action.todo);
16 | break;
17 |
18 | case 'TODO_DELETE':
19 | console.log("Handling TODO_DELETE using dispatcher in store");
20 | TodoStore.deleteTodo(action.todo);
21 | break;
22 |
23 | case 'TODO_ADD':
24 | console.log("Handling TODO_ADD using dispatcher in store");
25 | TodoStore.getTodos();
26 | break;
27 | }
28 |
29 | });
30 |
31 | var _todos = {};
32 | var CHANGE_EVENT = 'change';
33 |
34 | var TodoStore = assign({}, EventEmitter.prototype, {
35 |
36 | deleteTodo: (todo) => {
37 | var newTodos = _todos.filter( (t) => {
38 | return t.id != todo.id
39 | } )
40 | _todos = newTodos;
41 | TodoStore.emitChange();
42 | },
43 |
44 | markTodoDone: (todo) => {
45 | var _todo = _todos.filter((t) => {
46 | return t.id === todo.id;
47 | })[0];
48 |
49 | _todo.done = true;
50 | TodoStore.emitChange();
51 | },
52 |
53 | markTodoUnDone: (todo) => {
54 | var _todo = _todos.filter((t) => {
55 | return t.id === todo.id;
56 | })[0];
57 |
58 | _todo.done = false;
59 | TodoStore.emitChange();
60 | },
61 |
62 | setTodos: (todos) => {
63 | _todos = todos;
64 | TodoStore.emitChange();
65 | },
66 |
67 | getTodos: () => {
68 | return _todos;
69 | },
70 |
71 | emitChange: function() {
72 | this.emit(CHANGE_EVENT);
73 | },
74 |
75 | addChangeListener: function (callback) {
76 | console.log("registering callback for changelistener");
77 | this.on(CHANGE_EVENT, callback);
78 | }
79 | })
80 |
81 | module.exports = TodoStore;
82 |
--------------------------------------------------------------------------------
/ep29-emit/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep29-emit/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep29-emit/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "flux": "^2.1.1",
27 | "jquery": "1.11.3",
28 | "object-assign": "^4.0.1",
29 | "random-key": "^0.3.2",
30 | "react": "^0.13.3",
31 | "whatwg-fetch": "^0.9.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ep29-emit/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/app/actions/TodoActions.js:
--------------------------------------------------------------------------------
1 | var api = require("../utils/api");
2 | var TodoStore = require("../stores/TodoStore");
3 | var AppDispatcher = require('../dispatcher/AppDispatcher');
4 |
5 | var TodoActions = {
6 |
7 | allTodos: () => {
8 | api.getTodos()
9 | .then( (responseData) => {
10 | console.log("Got All TODOs successfully");
11 | AppDispatcher.dispatch({
12 | actionType: 'TODO_ALL',
13 | todos: todos
14 | });
15 | })
16 | },
17 |
18 | addTodo: (todo) => {
19 | console.log("adding TODO");
20 | api.addTodo(todo)
21 | .then( () => {
22 | allTodos();
23 | })
24 | .then( () => {
25 | console.log("Added TODO successfully");
26 | AppDispatcher.dispatch({
27 | actionType: 'TODO_ADD'
28 | });
29 | })
30 | },
31 |
32 | deleteTodo: (todo) => {
33 | console.log("Deleting TODO");
34 | api.deleteTodo(todo.id)
35 | .then( () => {
36 | console.log("Deleted TODO successfully");
37 | AppDispatcher.dispatch({
38 | actionType: 'TODO_DELETE',
39 | todo: todo
40 | });
41 | })
42 | },
43 |
44 | markTodoDone: (todo) => {
45 | console.log("Marking TODO as done");
46 | api.markTodoDone(todo)
47 | .then( () => {
48 | console.log("marked TODO as done successfully");
49 | AppDispatcher.dispatch({
50 | actionType: 'TODO_DONE',
51 | todo: todo
52 | });
53 |
54 | })
55 | },
56 |
57 | markTodoUnDone: (todo) => {
58 | console.log("Marking TODO as undone");
59 | api.markTodoUnDone(todo)
60 | .then( () => {
61 | console.log("marked TODO as undone successfully");
62 | AppDispatcher.dispatch({
63 | actionType: 'TODO_UNDONE',
64 | todo: todo
65 | });
66 | })
67 | },
68 |
69 | }
70 |
71 | module.exports = TodoActions;
72 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TodoForm from './TodoForm';
3 | import DisplayList from './DisplayList';
4 |
5 | var rand = require('random-key');
6 | var api = require("../utils/api");
7 | var TodoActions = require("../actions/TodoActions");
8 | var TodoStore = require("../stores/TodoStore");
9 |
10 | export default class App extends React.Component {
11 |
12 | constructor () {
13 | super();
14 | this.state = { title: '', todos: [] };
15 |
16 | TodoActions.allTodos();
17 | }
18 |
19 | componentDidMount () {
20 | var storeIsTellingUsThatDataHasChanged = () => {
21 | console.log("Store is telling us that data has change");
22 | var todos = TodoStore.getTodos();
23 | console.log("todos :", todos);
24 | this.setState({todos: todos});
25 | }
26 | TodoStore.addChangeListener(storeIsTellingUsThatDataHasChanged);
27 | }
28 |
29 | handleClearCompleted (event) {
30 | var newTodos = this.state.todos.filter((todo) => { return !todo.done});
31 | this.setState({ todos: newTodos });
32 | }
33 |
34 | render () {
35 | return
36 |
37 |
39 |
45 |
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
19 | DisplayList.propTypes = {
20 | todos: React.PropTypes.array.isRequired
21 | }
22 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/app/components/TodoForm.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayList from './DisplayList';
3 | import DisplayItem from './DisplayItem';
4 |
5 | var TodoActions = require('../actions/TodoActions');
6 |
7 | export default class TodoForm extends React.Component {
8 |
9 | constructor () {
10 | super();
11 | this.state = { editing: false }
12 | }
13 |
14 | handleSubmit (event) {
15 | event.preventDefault();
16 |
17 | var newTodo = { title: this.state.title, done: false };
18 |
19 | TodoActions.addTodo(newTodo);
20 | this.setState({ title: '' });
21 | }
22 |
23 | handleChange (event) {
24 | var title = event.target.value;
25 | this.setState({ title: title });
26 | }
27 |
28 | render () {
29 | return
30 |
TODO
31 |
36 | ;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/app/dispatcher/AppDispatcher.js:
--------------------------------------------------------------------------------
1 | var Dispatcher = require('flux').Dispatcher;
2 |
3 | module.exports = new Dispatcher();
4 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "flux": "^2.1.1",
27 | "jquery": "1.11.3",
28 | "object-assign": "^4.0.1",
29 | "random-key": "^0.3.2",
30 | "react": "^0.13.3",
31 | "whatwg-fetch": "^0.9.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ep30-extract-form-into-componenet-from-app/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/README.md:
--------------------------------------------------------------------------------
1 | #### Setting up the application
2 |
3 | ```
4 | npm install
5 | npm start
6 | ```
7 |
8 | Visit http://localhost:8080 in browser.
9 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/app/actions/TodoActions.js:
--------------------------------------------------------------------------------
1 | var api = require("../utils/api");
2 | var TodoStore = require("../stores/TodoStore");
3 | var AppDispatcher = require('../dispatcher/AppDispatcher');
4 |
5 | var TodoActions = {
6 |
7 | addTodo: (todo) => {
8 | console.log("adding TODO");
9 | api.addTodo(todo)
10 | .then( () => {
11 | api.getTodos()
12 | .then( (responseData) => {
13 | var todos = responseData.todos;
14 | console.log("All todos", todos);
15 | TodoStore.setTodos(todos);
16 | })
17 | })
18 | .then( () => {
19 | console.log("Added TODO successfully");
20 | AppDispatcher.dispatch({
21 | actionType: 'TODO_ADD'
22 | });
23 | })
24 | },
25 |
26 | deleteTodo: (todo) => {
27 | console.log("Deleting TODO");
28 | api.deleteTodo(todo.id)
29 | .then( () => {
30 | console.log("Deleted TODO successfully");
31 | AppDispatcher.dispatch({
32 | actionType: 'TODO_DELETE',
33 | todo: todo
34 | });
35 | })
36 | },
37 |
38 | markTodoDone: (todo) => {
39 | console.log("Marking TODO as done");
40 | api.markTodoDone(todo)
41 | .then( () => {
42 | console.log("marked TODO as done successfully");
43 | AppDispatcher.dispatch({
44 | actionType: 'TODO_DONE',
45 | todo: todo
46 | });
47 |
48 | })
49 | },
50 |
51 | markTodoUnDone: (todo) => {
52 | console.log("Marking TODO as undone");
53 | api.markTodoUnDone(todo)
54 | .then( () => {
55 | console.log("marked TODO as undone successfully");
56 | AppDispatcher.dispatch({
57 | actionType: 'TODO_UNDONE',
58 | todo: todo
59 | });
60 | })
61 | },
62 |
63 | }
64 |
65 | module.exports = TodoActions;
66 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/app/components/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import TodoForm from './TodoForm';
3 | import DisplayList from './DisplayList';
4 |
5 | var rand = require('random-key');
6 | var api = require("../utils/api");
7 | var TodoActions = require("../actions/TodoActions");
8 | var TodoStore = require("../stores/TodoStore");
9 |
10 | export default class App extends React.Component {
11 |
12 | constructor () {
13 | super();
14 | this.state = { title: '', todos: [] };
15 |
16 | this.getAllTodos();
17 | }
18 |
19 | componentDidMount () {
20 | var storeIsTellingUsThatDataHasChanged = () => {
21 | console.log("Store is telling us that data has change");
22 | var todos = TodoStore.getTodos();
23 | console.log("todos is");
24 | console.log(todos);
25 | this.setState({todos: todos});
26 | }
27 | TodoStore.addChangeListener(storeIsTellingUsThatDataHasChanged);
28 | }
29 |
30 | getAllTodos () {
31 | api.getTodos()
32 | .then( (responseData) => {
33 | var todos = responseData.todos;
34 | this.setState({todos: todos });
35 | TodoStore.setTodos(todos);
36 | })
37 | }
38 |
39 | handleClearCompleted (event) {
40 | var newTodos = this.state.todos.filter((todo) => { return !todo.done});
41 | this.setState({ todos: newTodos });
42 | }
43 |
44 | render () {
45 | return
46 |
47 |
49 |
55 |
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/app/components/DisplayList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayItem from './DisplayItem';
3 |
4 | export default class DisplayList extends React.Component {
5 |
6 | render () {
7 | return
8 | { this.props.todos.map((todo, i) => {
9 | return
13 | }) }
14 |
15 | }
16 |
17 | }
18 |
19 | DisplayList.propTypes = {
20 | todos: React.PropTypes.array.isRequired
21 | }
22 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/app/components/TodoForm.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import DisplayList from './DisplayList';
3 | import DisplayItem from './DisplayItem';
4 |
5 | var TodoActions = require('../actions/TodoActions');
6 |
7 | export default class TodoForm extends React.Component {
8 |
9 | constructor () {
10 | super();
11 | this.state = { editing: false }
12 | }
13 |
14 | handleSubmit (event) {
15 | event.preventDefault();
16 |
17 | var newTodo = { title: this.state.title, done: false };
18 |
19 | TodoActions.addTodo(newTodo);
20 | this.setState({ title: '' });
21 | }
22 |
23 | handleChange (event) {
24 | var title = event.target.value;
25 | this.setState({ title: title });
26 | }
27 |
28 | render () {
29 | return
30 |
TODO
31 |
36 | ;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/app/dispatcher/AppDispatcher.js:
--------------------------------------------------------------------------------
1 | var Dispatcher = require('flux').Dispatcher;
2 |
3 | module.exports = new Dispatcher();
4 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/app/main.jsx:
--------------------------------------------------------------------------------
1 | import './stylesheets/main.css';
2 |
3 | import React from 'react';
4 | import App from './components/App';
5 |
6 | main();
7 |
8 | function main() {
9 | var div = document.createElement('div');
10 | div.setAttribute("id", "todoapp");
11 | document.body.appendChild(div);
12 |
13 | React.render(, div);
14 | }
15 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/app/stores/TodoStore.js:
--------------------------------------------------------------------------------
1 | var AppDispatcher = require('../dispatcher/AppDispatcher');
2 | var EventEmitter = require('events').EventEmitter;
3 | var assign = require('object-assign');
4 |
5 | AppDispatcher.register(function(action) {
6 |
7 | switch(action.actionType) {
8 | case 'TODO_DONE':
9 | console.log("Handling TODO_DONE using dispatcher in store");
10 | TodoStore.markTodoDone(action.todo);
11 | break;
12 |
13 | case 'TODO_UNDONE':
14 | console.log("Handling TODO_UNDONE using dispatcher in store");
15 | TodoStore.markTodoUnDone(action.todo);
16 | break;
17 |
18 | case 'TODO_DELETE':
19 | console.log("Handling TODO_DELETE using dispatcher in store");
20 | TodoStore.deleteTodo(action.todo);
21 | break;
22 |
23 | case 'TODO_ADD':
24 | console.log("Handling TODO_ADD using dispatcher in store");
25 | TodoStore.getTodos();
26 | break;
27 | }
28 |
29 | });
30 |
31 | var _todos = {};
32 | var CHANGE_EVENT = 'change';
33 |
34 | var TodoStore = assign({}, EventEmitter.prototype, {
35 |
36 | deleteTodo: (todo) => {
37 | var newTodos = _todos.filter( (t) => {
38 | return t.id != todo.id
39 | } )
40 | _todos = newTodos;
41 | TodoStore.emitChange();
42 | },
43 |
44 | markTodoDone: (todo) => {
45 | var _todo = _todos.filter((t) => {
46 | return t.id === todo.id;
47 | })[0];
48 |
49 | _todo.done = true;
50 | TodoStore.emitChange();
51 | },
52 |
53 | markTodoUnDone: (todo) => {
54 | var _todo = _todos.filter((t) => {
55 | return t.id === todo.id;
56 | })[0];
57 |
58 | _todo.done = false;
59 | TodoStore.emitChange();
60 | },
61 |
62 | setTodos: (todos) => {
63 | _todos = todos;
64 | TodoStore.emitChange();
65 | },
66 |
67 | getTodos: () => {
68 | return _todos;
69 | },
70 |
71 | emitChange: function() {
72 | this.emit(CHANGE_EVENT);
73 | },
74 |
75 | addChangeListener: function (callback) {
76 | console.log("registering callback for changelistener");
77 | this.on(CHANGE_EVENT, callback);
78 | }
79 | })
80 |
81 | module.exports = TodoStore;
82 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/app/utils/api.js:
--------------------------------------------------------------------------------
1 | require('whatwg-fetch');
2 | var Constants = require("./constants");
3 | var HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }
4 |
5 | var api = {
6 | generateUrlWithApiKey(endpoint) {
7 | return Constants.BASE_URL + endpoint + '?api_key=' + Constants.API_KEY;
8 | },
9 |
10 | getTodos () {
11 | var url = this.generateUrlWithApiKey('todos');
12 | return fetch(url)
13 | .then((res) => res.json())
14 | .catch( (error) => console.log('Failed to get all tasks list.', error) );
15 | },
16 |
17 | addTodo (todo) {
18 | var url = this.generateUrlWithApiKey('todos');
19 | var options = {
20 | method: 'POST',
21 | headers: HEADER,
22 | body: JSON.stringify({todo: todo})
23 | };
24 | return fetch(url, options)
25 | .then((res) => res.json())
26 | .catch( (error) => console.log('Failed to add a TODO.', error) );
27 | },
28 |
29 | markTodoDone (todo) {
30 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
31 | var options = {
32 | method: 'PUT',
33 | headers: HEADER,
34 | body: JSON.stringify({done: true})
35 | };
36 | return fetch(url, options)
37 | .then((res) => res.json())
38 | .catch( (error) => console.log('Failed to mark task as done. ', error) );
39 | },
40 |
41 | markTodoUnDone (todo) {
42 | var url = this.generateUrlWithApiKey('todos/' + todo.id);
43 | var options = {
44 | method: 'PUT',
45 | headers: HEADER,
46 | body: JSON.stringify({done: false})
47 | };
48 | return fetch(url, options)
49 | .then((res) => res.json())
50 | .catch( (error) => console.log('Failed to mark task as undone. ', error) );
51 | },
52 |
53 | deleteTodo (idToBeDeleted, processDataCallback) {
54 | var url = this.generateUrlWithApiKey('todos/' + idToBeDeleted);
55 | return fetch(url, { method: 'DELETE' })
56 | .then((res) => res.json())
57 | .catch( (error) => console.log('Failed to delete TODO.', error) );
58 | },
59 |
60 | };
61 |
62 | module.exports = api;
63 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/app/utils/constants.js:
--------------------------------------------------------------------------------
1 | var Constants = {
2 | BASE_URL: "http://lrjis-api-production.herokuapp.com/api/v1/",
3 | API_KEY: "4d5e466a-97a4-46ba-bb3d-3da6c4347965"
4 | };
5 | module.exports = Constants;
6 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learning-reactjs-in-steps",
3 | "version": "0.0.1",
4 | "description": "Learn ReactJS in steps",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "TAGET=build webpack",
9 | "start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10 | },
11 | "author": "Neeraj Singh",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "babel-core": "^5.6.15",
15 | "babel-loader": "^5.3.1",
16 | "css-loader": "^0.15.1",
17 | "html-webpack-plugin": "^1.5.2",
18 | "node-libs-browser": "^0.5.2",
19 | "react-hot-loader": "^1.2.7",
20 | "style-loader": "^0.12.3",
21 | "webpack": "^1.10.1",
22 | "webpack-dev-server": "^1.10.1",
23 | "webpack-merge": "^0.1.2"
24 | },
25 | "dependencies": {
26 | "flux": "^2.1.1",
27 | "jquery": "1.11.3",
28 | "object-assign": "^4.0.1",
29 | "random-key": "^0.3.2",
30 | "react": "^0.13.3",
31 | "whatwg-fetch": "^0.9.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ep31-get-all-todos/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 | var merge = require('webpack-merge');
4 |
5 | var TARGET = process.env.TARGET;
6 | var ROOT_PATH = path.resolve(__dirname);
7 |
8 | var common = {
9 | entry: [path.resolve(ROOT_PATH, 'app/main')],
10 | resolve: {
11 | extensions: ['', '.js', '.jsx'],
12 | },
13 | output: {
14 | path: path.resolve(ROOT_PATH, 'build'),
15 | filename: 'bundle.js',
16 | },
17 | plugins: [
18 | new HtmlWebpackPlugin({ title: 'Todo app', }),
19 | ],
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.css$/,
24 | loaders: ['style', 'css'],
25 | },
26 | {
27 | test: /\.jsx?$/,
28 | loader: 'babel?stage=1',
29 | include: path.resolve(ROOT_PATH, 'app'),
30 | }
31 | ],
32 | },
33 | };
34 |
35 | if (TARGET === 'build') {
36 | module.exports = common;
37 | }
38 |
39 | if (TARGET === 'dev') {
40 | module.exports = merge(common, {
41 | entry: [
42 | 'webpack-dev-server/client?http://0.0.0.0:8080',
43 | 'webpack/hot/dev-server'
44 | ],
45 | module: {
46 | loaders: [ {
47 | test: /\.jsx?$/,
48 | loaders: ['react-hot', 'babel?stage=1'],
49 | include: path.resolve(ROOT_PATH, 'app'),
50 | },
51 | ],
52 | },
53 | });
54 | }
55 |
--------------------------------------------------------------------------------