├── 01-react-tryout └── index.html ├── 02-environment-setup └── webpack │ ├── .gitignore │ ├── README.md │ ├── node_modules │ └── .gitignore │ ├── package.json │ ├── public │ └── index.html │ ├── src │ ├── components │ │ └── App.js │ └── index.js │ └── webpack.config.js ├── 03-jsx ├── .gitignore ├── .jshintrc ├── .tern-project ├── README.md ├── index.html ├── node_modules │ └── .gitignore ├── package.json ├── src │ └── App.js └── webpack.config.js ├── 04-component ├── .gitignore ├── .jshintrc ├── README.md ├── node_modules │ └── .gitignore ├── package.json ├── public │ └── index.html ├── src │ ├── components │ │ ├── App.js │ │ ├── Content.js │ │ └── Header.js │ └── index.js └── webpack.config.js ├── 05-state-and-props ├── .gitignore ├── .jshintrc ├── README.md ├── node_modules │ └── .gitignore ├── package.json ├── public │ └── index.html ├── src │ ├── components │ │ ├── App.js │ │ ├── Content.js │ │ ├── Header.js │ │ ├── RandomNumber.js │ │ └── StateExample.js │ └── index.js └── webpack.config.js ├── 06-component-iteration ├── .gitignore ├── .jshintrc ├── README.md ├── index.html ├── node_modules │ └── .gitignore ├── package.json ├── preview.png ├── src │ └── App.js └── webpack.config.js ├── 09-router ├── .gitignore ├── README.md ├── index.html ├── node_modules │ └── .gitignore ├── package.json ├── src │ └── App.js └── webpack.config.js ├── 10-redux ├── .gitignore ├── README.md ├── index.html ├── package.json ├── src │ ├── actions │ │ └── index.js │ ├── components │ │ ├── App.js │ │ ├── Buttons.js │ │ ├── Counter.js │ │ └── Option.js │ ├── index.js │ ├── index_without_reactredux.js │ └── reducers │ │ └── index.js └── webpack.config.js ├── 11-using-express-hmr ├── .babelrc ├── .gitignore ├── README.md ├── package.json ├── public │ └── index.html ├── server │ ├── main.js │ └── routes │ │ └── posts.js ├── src │ ├── App.js │ └── index.js ├── webpack.config.js └── webpack.dev.config.js └── README.md /01-react-tryout/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React Tutorial 7 | 8 | 9 | 10 | 11 | 12 |
13 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /02-environment-setup/webpack/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/*/ 2 | .jshintrc 3 | -------------------------------------------------------------------------------- /02-environment-setup/webpack/README.md: -------------------------------------------------------------------------------- 1 | # REACT.JS ENVIRONMENT SETUP - WEBPACK 2 | 3 | Link to blog post - (KOREAN) [[React JS] 강좌 2편 작업환경 설정하기](http://velopert.com/814) 4 | 5 | This project uses React 0.14.7, Babel 6 and Webpack to setup the development 6 | environment for React.js on NodeJS 7 | 8 | ## How to install 9 | - Run ``npm install`` to install the dependency 10 | - Run ``npm start`` to run the development server 11 | 12 | 13 | *Server port is set to **7777*** 14 | -------------------------------------------------------------------------------- /02-environment-setup/webpack/node_modules/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velopert/react-tutorials/ad4304541bad5c9ba6cd12338aedf4d86970857f/02-environment-setup/webpack/node_modules/.gitignore -------------------------------------------------------------------------------- /02-environment-setup/webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_tutorial", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "./node_modules/.bin/webpack-dev-server --hot --host 0.0.0.0" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "react": "^0.14.7", 13 | "react-dom": "^0.14.7" 14 | }, 15 | "devDependencies": { 16 | "babel-core": "^6.7.0", 17 | "babel-loader": "^6.2.4", 18 | "babel-preset-es2015": "^6.6.0", 19 | "babel-preset-react": "^6.5.0", 20 | "webpack": "^1.12.14", 21 | "webpack-dev-server": "^1.14.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /02-environment-setup/webpack/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React App 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /02-environment-setup/webpack/src/components/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class App extends React.Component { 4 | render(){ 5 | 6 | return ( 7 |

Hello Velopert

8 | ); 9 | } 10 | } 11 | 12 | export default App; 13 | -------------------------------------------------------------------------------- /02-environment-setup/webpack/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './components/App'; 4 | 5 | const rootElement = document.getElementById('root'); 6 | ReactDOM.render(, rootElement); 7 | -------------------------------------------------------------------------------- /02-environment-setup/webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './src/index.js', 3 | 4 | output: { 5 | path: __dirname + '/public', 6 | filename: 'bundle.js' 7 | }, 8 | 9 | devServer: { 10 | inline: true, 11 | port: 7777, 12 | contentBase: __dirname + '/public' 13 | }, 14 | 15 | module: 16 | { 17 | loaders: [ 18 | { 19 | test: /\.js$/, 20 | loader: 'babel', 21 | exclude: /node_modules/, 22 | query: { 23 | cacheDirectory: true, 24 | presets: ['es2015', 'react'] 25 | } 26 | } 27 | ] 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /03-jsx/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/*/ 2 | -------------------------------------------------------------------------------- /03-jsx/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "exnext": true 3 | } 4 | -------------------------------------------------------------------------------- /03-jsx/.tern-project: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaVersion": 6, 3 | "libs": [] 4 | } 5 | -------------------------------------------------------------------------------- /03-jsx/README.md: -------------------------------------------------------------------------------- 1 | # REACT.JS JSX 2 | 3 | -------------------------------------------------------------------------------- /03-jsx/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React App 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /03-jsx/node_modules/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /03-jsx/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_tutorial", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "./node_modules/.bin/webpack-dev-server --hot --host 0.0.0.0" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "react": "^0.14.7", 13 | "react-dom": "^0.14.7" 14 | }, 15 | "devDependencies": { 16 | "babel-core": "^6.7.0", 17 | "babel-loader": "^6.2.4", 18 | "babel-preset-es2015": "^6.6.0", 19 | "babel-preset-react": "^6.5.0", 20 | "webpack": "^1.12.14", 21 | "webpack-dev-server": "^1.14.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /03-jsx/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | class App extends React.Component { 5 | _sayHey(){ 6 | alert("hey"); 7 | } 8 | 9 | render(){ 10 | let text = "Dev-Server"; 11 | 12 | let pStyle = { 13 | color: 'aqua', 14 | backgroundColor: 'black' 15 | }; 16 | 17 | return ( 18 |
19 |

Hello Velopert

20 |

Welcome to {text}

21 | 22 |

{1 == 1 ? 'True' : 'False'}

23 | 24 | { /* COMMENT */ } 25 |
26 | ); 27 | } 28 | } 29 | 30 | ReactDOM.render(, document.getElementById('app')); 31 | -------------------------------------------------------------------------------- /03-jsx/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './src/App.js', 3 | 4 | output: { 5 | path: __dirname, 6 | filename: 'app.js' 7 | }, 8 | 9 | devServer: { 10 | inline: true, 11 | port: 7777 12 | }, 13 | 14 | module: 15 | { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | loader: 'babel', 20 | exclude: /node_modules/, 21 | query: { 22 | cacheDirectory: true, 23 | presets: ['es2015', 'react'] 24 | } 25 | } 26 | ] 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /04-component/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/*/ 2 | -------------------------------------------------------------------------------- /04-component/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esversion": 6 3 | } 4 | -------------------------------------------------------------------------------- /04-component/README.md: -------------------------------------------------------------------------------- 1 | # REACT.JS COMPONENT 2 | -------------------------------------------------------------------------------- /04-component/node_modules/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /04-component/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_tutorial", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "./node_modules/.bin/webpack-dev-server --hot --host 0.0.0.0" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "react": "^0.14.7", 13 | "react-dom": "^0.14.7" 14 | }, 15 | "devDependencies": { 16 | "babel-core": "^6.7.0", 17 | "babel-loader": "^6.2.4", 18 | "babel-preset-es2015": "^6.6.0", 19 | "babel-preset-react": "^6.5.0", 20 | "webpack": "^1.12.14", 21 | "webpack-dev-server": "^1.14.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /04-component/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React App 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /04-component/src/components/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Header from './Header'; 3 | import Content from './Content'; 4 | 5 | class App extends React.Component { 6 | render(){ 7 | return ( 8 |
9 |
10 | 11 |
12 | ); 13 | } 14 | } 15 | 16 | export default App; 17 | -------------------------------------------------------------------------------- /04-component/src/components/Content.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | 4 | class Content extends React.Component { 5 | render(){ 6 | return ( 7 |
8 |

Content

9 |

Hey!

10 |
11 | ); 12 | } 13 | } 14 | 15 | export default Content; 16 | -------------------------------------------------------------------------------- /04-component/src/components/Header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | 4 | class Header extends React.Component { 5 | render(){ 6 | return ( 7 |

Header

8 | ); 9 | } 10 | } 11 | 12 | export default Header; 13 | -------------------------------------------------------------------------------- /04-component/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './components/App' 4 | 5 | const rootElement = document.getElementById('root'); 6 | ReactDOM.render(, rootElement); 7 | -------------------------------------------------------------------------------- /04-component/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './src/index.js', 3 | 4 | output: { 5 | path: __dirname + '/public/', 6 | filename: 'bundle.js' 7 | }, 8 | 9 | devServer: { 10 | inline: true, 11 | port: 7777, 12 | contentBase: __dirname + '/public/' 13 | }, 14 | 15 | module: 16 | { 17 | loaders: [ 18 | { 19 | test: /\.js$/, 20 | loader: 'babel', 21 | exclude: /node_modules/, 22 | query: { 23 | cacheDirectory: true, 24 | presets: ['es2015', 'react'] 25 | } 26 | } 27 | ] 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /05-state-and-props/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/*/ 2 | -------------------------------------------------------------------------------- /05-state-and-props/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esversion": 6 3 | } 4 | -------------------------------------------------------------------------------- /05-state-and-props/README.md: -------------------------------------------------------------------------------- 1 | # REACT.JS COMPONENT 2 | -------------------------------------------------------------------------------- /05-state-and-props/node_modules/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /05-state-and-props/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_tutorial", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "./node_modules/.bin/webpack-dev-server --hot --host 0.0.0.0" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "react": "^0.14.7", 13 | "react-dom": "^0.14.7" 14 | }, 15 | "devDependencies": { 16 | "babel-core": "^6.7.0", 17 | "babel-loader": "^6.2.4", 18 | "babel-preset-es2015": "^6.6.0", 19 | "babel-preset-react": "^6.5.0", 20 | "webpack": "^1.12.14", 21 | "webpack-dev-server": "^1.14.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /05-state-and-props/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React App 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /05-state-and-props/src/components/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Header from './Header'; 3 | import Content from './Content'; 4 | import RandomNumber from './RandomNumber'; 5 | 6 | class App extends React.Component { 7 | 8 | constructor(props){ 9 | super(props); 10 | 11 | this.state = { 12 | value: Math.round(Math.random()*100) 13 | }; 14 | 15 | this._updateValue = this._updateValue.bind(this); 16 | } 17 | 18 | render(){ 19 | return ( 20 |
21 |
22 | 24 | 26 |
27 | ); 28 | } 29 | 30 | _updateValue(randomValue){ 31 | this.setState({ 32 | value: randomValue 33 | }); 34 | } 35 | } 36 | 37 | App.defaultProps = { 38 | header: 'Default header', 39 | contentTitle: 'Default contentTitle', 40 | contentBody: 'Default contentBody' 41 | } 42 | 43 | export default App; 44 | -------------------------------------------------------------------------------- /05-state-and-props/src/components/Content.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | 4 | class Content extends React.Component { 5 | render(){ 6 | return ( 7 |
8 |

{ this.props.title }

9 |

{ this.props.body }

10 |
11 | ); 12 | } 13 | } 14 | 15 | Content.propTypes = { 16 | title: React.PropTypes.string, 17 | body: React.PropTypes.string.isRequired 18 | }; 19 | 20 | export default Content; 21 | -------------------------------------------------------------------------------- /05-state-and-props/src/components/Header.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | 4 | class Header extends React.Component { 5 | render(){ 6 | return ( 7 |

{ this.props.title }

8 | ); 9 | } 10 | } 11 | 12 | export default Header; 13 | -------------------------------------------------------------------------------- /05-state-and-props/src/components/RandomNumber.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | 5 | class RandomNumber extends React.Component { 6 | _update(){ 7 | let value = Math.round(Math.random()*100); 8 | this.props.onUpdate(value); 9 | } 10 | 11 | constructor(props){ 12 | super(props); 13 | this._update = this._update.bind(this); 14 | } 15 | 16 | render(){ 17 | return ( 18 |
19 |

RANDOM NUMBER: { this.props.number }

20 | 21 |
22 | ); 23 | } 24 | } 25 | 26 | export default RandomNumber; 27 | -------------------------------------------------------------------------------- /05-state-and-props/src/components/StateExample.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | class StateExample extends React.Component { 4 | constructor(props) { 5 | super(props); 6 | 7 | this.state = { 8 | header: "Header Initial state", 9 | content: "Content Initial State" 10 | }; 11 | } 12 | 13 | _updateHeader(text){ 14 | this.setState({ 15 | header: "Header has changed" 16 | }); 17 | } 18 | 19 | render() { 20 | return ( 21 |
22 |

{this.state.header}

23 |

{this.state.content}

24 | 25 |
26 | ); 27 | } 28 | } 29 | 30 | export default StateExample; 31 | -------------------------------------------------------------------------------- /05-state-and-props/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './components/App' 4 | 5 | const rootElement = document.getElementById('root'); 6 | ReactDOM.render(, rootElement); 7 | -------------------------------------------------------------------------------- /05-state-and-props/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './src/index.js', 3 | 4 | output: { 5 | path: __dirname + '/public/', 6 | filename: 'bundle.js' 7 | }, 8 | 9 | devServer: { 10 | inline: true, 11 | port: 7777, 12 | contentBase: __dirname + '/public/' 13 | }, 14 | 15 | module: 16 | { 17 | loaders: [ 18 | { 19 | test: /\.js$/, 20 | loader: 'babel', 21 | exclude: /node_modules/, 22 | query: { 23 | cacheDirectory: true, 24 | presets: ['es2015', 'react'] 25 | } 26 | } 27 | ] 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /06-component-iteration/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/*/ 2 | -------------------------------------------------------------------------------- /06-component-iteration/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esversion": 6 3 | } 4 | -------------------------------------------------------------------------------- /06-component-iteration/README.md: -------------------------------------------------------------------------------- 1 | ## React Component Iteration thru Mapping & Using Immutability Helper 2 | Link to blog post - (KOREAN) [[React.JS] 강좌 6-2편 Immutability Helper – State 내부 Array 에 원소 삽입/제거/수정](https://velopert.com/1015) 3 | 4 | [![Image](https://raw.githubusercontent.com/velopert/react-tutorials/master/06-component-iteration/preview.png)](https://jsfiddle.net/velopert/k21ozagp/17/) 5 | -------------------------------------------------------------------------------- /06-component-iteration/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React App 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /06-component-iteration/node_modules/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velopert/react-tutorials/ad4304541bad5c9ba6cd12338aedf4d86970857f/06-component-iteration/node_modules/.gitignore -------------------------------------------------------------------------------- /06-component-iteration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_tutorial", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "./node_modules/.bin/webpack-dev-server --hot --host 0.0.0.0" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "react": "^0.14.7", 13 | "react-addons-update": "^0.14.7", 14 | "react-dom": "^0.14.7" 15 | }, 16 | "devDependencies": { 17 | "babel-core": "^6.7.0", 18 | "babel-loader": "^6.2.4", 19 | "babel-preset-es2015": "^6.6.0", 20 | "babel-preset-react": "^6.5.0", 21 | "webpack": "^1.12.14", 22 | "webpack-dev-server": "^1.14.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /06-component-iteration/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velopert/react-tutorials/ad4304541bad5c9ba6cd12338aedf4d86970857f/06-component-iteration/preview.png -------------------------------------------------------------------------------- /06-component-iteration/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import update from 'react-addons-update'; 4 | 5 | class App extends React.Component { 6 | render(){ 7 | 8 | return ( 9 | 10 | ); 11 | } 12 | } 13 | 14 | class Contacts extends React.Component { 15 | constructor(props) { 16 | super(props); 17 | this.state = { 18 | contactData: [ 19 | {name: "Abet", phone: "010-0000-0001"}, 20 | {name: "Betty", phone: "010-0000-0002"}, 21 | {name: "Charlie", phone: "010-0000-0003"}, 22 | {name: "David", phone: "010-0000-0004"} 23 | ], 24 | selectedKey: -1, 25 | selected: { 26 | name: "", 27 | phone: "" 28 | } 29 | }; 30 | } 31 | 32 | _insertContact(name, phone){ 33 | let newState = update(this.state, { 34 | contactData: { 35 | $push: [{"name": name, "phone": phone}] 36 | } 37 | }); 38 | this.setState(newState); 39 | } 40 | 41 | 42 | _onSelect(key){ 43 | if(key==this.state.selectedKey){ 44 | console.log("key select cancelled"); 45 | this.setState({ 46 | selectedKey: -1, 47 | selected: { 48 | name: "", 49 | phone: "" 50 | } 51 | }); 52 | return; 53 | } 54 | 55 | this.setState({ 56 | selectedKey: key, 57 | selected: this.state.contactData[key] 58 | }); 59 | console.log(key + " is selected"); 60 | } 61 | 62 | _isSelected(key){ 63 | if(this.state.selectedKey == key){ 64 | return true; 65 | }else{ 66 | return false; 67 | } 68 | } 69 | 70 | _removeContact(){ 71 | if(this.state.selectedKey==-1){ 72 | console.log("contact not selected"); 73 | return; 74 | } 75 | 76 | this.setState({ 77 | contactData: update( 78 | this.state.contactData, 79 | { 80 | $splice: [[this.state.selectedKey, 1]] 81 | } 82 | ), 83 | selectedKey: -1 84 | }); 85 | } 86 | 87 | _editContact(name, phone){ 88 | this.setState({ 89 | contactData: update( 90 | this.state.contactData, 91 | { 92 | [this.state.selectedKey]: { 93 | name: { $set: name }, 94 | phone: { $set: phone } 95 | } 96 | } 97 | ), 98 | selected: { 99 | name: name, 100 | phone: phone 101 | } 102 | }); 103 | } 104 | 105 | 106 | 107 | render(){ 108 | return( 109 |
110 |

Contacts

111 |
    112 | {this.state.contactData.map((contact, i) => { 113 | return (); 119 | })} 120 |
121 | 122 | 123 | 126 |
127 | ); 128 | } 129 | } 130 | 131 | 132 | class ContactInfo extends React.Component { 133 | 134 | handleClick(){ 135 | this.props.onSelect(this.props.contactKey); 136 | } 137 | 138 | shouldComponentUpdate(nextProps, nextState){ 139 | return (JSON.stringify(nextProps) != JSON.stringify(this.props)); 140 | } 141 | 142 | render() { 143 | console.log("rendered: " + this.props.name); 144 | 145 | let getStyle = isSelect => { 146 | if(!isSelect) return; 147 | 148 | let style = { 149 | fontWeight: 'bold', 150 | backgroundColor: '#4efcd8' 151 | }; 152 | 153 | return style; 154 | }; 155 | 156 | return( 157 |
  • 159 | {this.props.name} {this.props.phone} 160 |
  • 161 | ); 162 | } 163 | } 164 | 165 | class ContactCreator extends React.Component { 166 | constructor(props) { 167 | super(constructor); 168 | // Configure default state 169 | this.state = { 170 | name: "", 171 | phone: "" 172 | }; 173 | } 174 | 175 | handleClick(){ 176 | this.props.onInsert(this.state.name, this.state.phone); 177 | this.setState({ 178 | name: "", 179 | phone: "" 180 | }); 181 | } 182 | 183 | handleChange(e){ 184 | var nextState = {}; 185 | nextState[e.target.name] = e.target.value; 186 | this.setState(nextState); 187 | } 188 | 189 | render() { 190 | return ( 191 |
    192 |

    193 | 198 | 199 | 204 | 207 |

    208 |
    209 | ); 210 | } 211 | } 212 | 213 | class ContactRemover extends React.Component { 214 | handleClick() { 215 | this.props.onRemove(); 216 | } 217 | 218 | render() { 219 | return ( 220 | 223 | ); 224 | } 225 | } 226 | 227 | class ContactEditor extends React.Component { 228 | constructor(props) { 229 | super(constructor); 230 | // Configure default state 231 | this.state = { 232 | name: "", 233 | phone: "" 234 | }; 235 | } 236 | 237 | handleClick(){ 238 | if(!this.props.isSelected){ 239 | console.log("contact not selected"); 240 | 241 | return; 242 | } 243 | 244 | this.props.onEdit(this.state.name, this.state.phone); 245 | } 246 | 247 | handleChange(e){ 248 | var nextState = {}; 249 | nextState[e.target.name] = e.target.value; 250 | this.setState(nextState); 251 | } 252 | 253 | componentWillReceiveProps(nextProps){ 254 | this.setState({ 255 | name: nextProps.contact.name, 256 | phone: nextProps.contact.phone 257 | }); 258 | } 259 | 260 | render() { 261 | return ( 262 |
    263 |

    264 | 269 | 270 | 275 | 278 |

    279 |
    280 | ); 281 | } 282 | } 283 | 284 | ReactDOM.render(, document.getElementById('app')); 285 | -------------------------------------------------------------------------------- /06-component-iteration/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './src/App.js', 3 | 4 | output: { 5 | path: __dirname, 6 | filename: 'app.js' 7 | }, 8 | 9 | devServer: { 10 | inline: true, 11 | port: 7777 12 | }, 13 | 14 | module: 15 | { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | loader: 'babel', 20 | exclude: /node_modules/, 21 | query: { 22 | cacheDirectory: true, 23 | presets: ['es2015', 'react'] 24 | } 25 | } 26 | ] 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /09-router/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/*/ 2 | .jshintrc 3 | ./app.js 4 | -------------------------------------------------------------------------------- /09-router/README.md: -------------------------------------------------------------------------------- 1 | # REACT.JS TUTORIAL - ROUTER 2 | -------------------------------------------------------------------------------- /09-router/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React App 7 | 8 | 9 | 10 |
    11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /09-router/node_modules/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/velopert/react-tutorials/ad4304541bad5c9ba6cd12338aedf4d86970857f/09-router/node_modules/.gitignore -------------------------------------------------------------------------------- /09-router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_tutorial", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "./node_modules/.bin/webpack-dev-server --hot --host 0.0.0.0" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "react": "^0.14.7", 13 | "react-dom": "^0.14.7", 14 | "react-router": "^2.0.1" 15 | }, 16 | "devDependencies": { 17 | "babel-core": "^6.7.0", 18 | "babel-loader": "^6.2.4", 19 | "babel-preset-es2015": "^6.6.0", 20 | "babel-preset-react": "^6.5.0", 21 | "webpack": "^1.12.14", 22 | "webpack-dev-server": "^1.14.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /09-router/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Router, Route, Link, browserHistory, IndexRoute} from 'react-router'; 4 | 5 | 6 | class App extends React.Component { 7 | render() { 8 | 9 | return ( 10 |
    11 |
      12 |
    • Home
    • 13 |
    • About
    • 14 |
    • Articles
    • 15 |
    16 | {this.props.children} 17 |
    18 | ); 19 | } 20 | } 21 | 22 | class Home extends React.Component { 23 | render() { 24 | return ( 25 |

    Hey, I am HOME!

    26 | ); 27 | } 28 | } 29 | 30 | class About extends React.Component { 31 | render() { 32 | return ( 33 |

    Hey, I am ABOUT!

    34 | ); 35 | } 36 | } 37 | 38 | class Articles extends React.Component { 39 | render() { 40 | return ( 41 |

    Hey, I am ARTCILES!

    42 | ); 43 | } 44 | } 45 | 46 | ReactDOM.render( 47 | 48 | 49 | 50 | 51 | 52 | 53 | , document.getElementById('app')); 54 | -------------------------------------------------------------------------------- /09-router/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './src/App.js', 3 | 4 | output: { 5 | path: __dirname, 6 | filename: 'app.js' 7 | }, 8 | 9 | devServer: { 10 | inline: true, 11 | port: 7777, 12 | historyApiFallback: true 13 | }, 14 | 15 | module: 16 | { 17 | loaders: [ 18 | { 19 | test: /\.js$/, 20 | loader: 'babel', 21 | exclude: /node_modules/, 22 | query: { 23 | cacheDirectory: true, 24 | presets: ['es2015', 'react'] 25 | } 26 | } 27 | ] 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /10-redux/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/*/ 2 | .jshintrc 3 | ./app.js 4 | -------------------------------------------------------------------------------- /10-redux/README.md: -------------------------------------------------------------------------------- 1 | # 10. redux 2 | -------------------------------------------------------------------------------- /10-redux/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React App 7 | 8 | 9 | 10 | 11 |
    12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /10-redux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react_tutorial", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "./node_modules/.bin/webpack-dev-server --hot --host 0.0.0.0" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "react": "^0.14.7", 13 | "react-dom": "^0.14.7", 14 | "react-redux": "^4.4.5", 15 | "redux": "^3.5.1" 16 | }, 17 | "devDependencies": { 18 | "babel-core": "^6.7.0", 19 | "babel-loader": "^6.2.4", 20 | "babel-preset-es2015": "^6.6.0", 21 | "babel-preset-react": "^6.5.0", 22 | "webpack": "^1.12.14", 23 | "webpack-dev-server": "^1.14.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /10-redux/src/actions/index.js: -------------------------------------------------------------------------------- 1 | export const INCREMENT = 'INCREMENT'; 2 | export const DECREMENT = 'DECREMENT'; 3 | export const SET_DIFF = 'SET_DIFF'; 4 | 5 | export function increment() { 6 | return { 7 | type: INCREMENT 8 | }; 9 | } 10 | 11 | export function decrement() { 12 | return { 13 | type: DECREMENT 14 | }; 15 | } 16 | 17 | export function setDiff(value) { 18 | return { 19 | type: SET_DIFF, 20 | diff: value 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /10-redux/src/components/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Counter from './Counter'; 3 | import Buttons from './Buttons'; 4 | import Option from './Option'; 5 | 6 | class App extends React.Component { 7 | render(){ 8 | return ( 9 |
    10 | 11 |
    14 | ); 15 | } 16 | 17 | } 18 | 19 | export default App; 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /10-redux/src/components/Buttons.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { increment, decrement } from '../actions'; 4 | 5 | class Buttons extends React.Component { 6 | render() { 7 | return ( 8 |
    9 | 13 | 17 |
    18 | ) 19 | } 20 | } 21 | 22 | 23 | let mapDispatchToProps = (dispatch) => { 24 | return { 25 | onIncrement: () => dispatch(increment()), 26 | onDecrement: () => dispatch(decrement()) 27 | } 28 | } 29 | 30 | Buttons = connect(undefined, mapDispatchToProps)(Buttons); 31 | 32 | export default Buttons; 33 | -------------------------------------------------------------------------------- /10-redux/src/components/Counter.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | 4 | class Counter extends React.Component { 5 | render() { 6 | return ( 7 |

    VALUE: { this.props.value }

    8 | ); 9 | } 10 | } 11 | 12 | let mapStateToProps = (state) => { 13 | return { 14 | value: state.counter.value 15 | }; 16 | } 17 | 18 | Counter = connect(mapStateToProps)(Counter); 19 | 20 | export default Counter; 21 | -------------------------------------------------------------------------------- /10-redux/src/components/Option.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { setDiff } from '../actions'; 4 | 5 | class Option extends React.Component { 6 | constructor(props) { 7 | super(props); 8 | 9 | this.state = { 10 | diff: '1' 11 | } 12 | 13 | 14 | this.onChangeDiff = this.onChangeDiff.bind(this); 15 | } 16 | 17 | render() { 18 | return ( 19 |
    20 | 21 |
    22 | ); 23 | } 24 | 25 | onChangeDiff(e) { 26 | 27 | if(isNaN(e.target.value)) 28 | return; 29 | 30 | this.setState({ diff: e.target.value }); 31 | 32 | if(e.target.value=='') { 33 | this.setState({ diff: '0' }); 34 | } 35 | 36 | this.props.onUpdateDiff(parseInt(e.target.value)); 37 | 38 | } 39 | } 40 | 41 | let mapDispatchToProps = (dispatch) => { 42 | return { 43 | onUpdateDiff: (value) => dispatch(setDiff(value)) 44 | }; 45 | } 46 | 47 | Option = connect(undefined, mapDispatchToProps)(Option); 48 | 49 | export default Option; 50 | -------------------------------------------------------------------------------- /10-redux/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { createStore } from 'redux'; 4 | import { Provider } from 'react-redux'; 5 | import App from './components/App'; 6 | import counterApp from './reducers'; 7 | 8 | const store = createStore(counterApp); 9 | const appElement = document.getElementById('app'); 10 | 11 | 12 | 13 | ReactDOM.render( 14 | 15 | 16 | , 17 | appElement 18 | ); 19 | -------------------------------------------------------------------------------- /10-redux/src/index_without_reactredux.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { createStore } from 'redux'; 4 | 5 | 6 | /* 7 | * Action 8 | */ 9 | const INCREMENT = "INCREMENT"; 10 | 11 | function increase(diff) { 12 | return { 13 | type: INCREMENT, 14 | addBy: diff 15 | }; 16 | } 17 | 18 | 19 | /* 20 | * Reducer 21 | */ 22 | const initialState = { 23 | value: 0 24 | }; 25 | 26 | const counterReducer = (state = initialState, action) => { 27 | switch(action.type) { 28 | case INCREMENT: 29 | return Object.assign({}, state, { 30 | value: state.value + action.addBy 31 | }); 32 | default: 33 | return state; 34 | } 35 | } 36 | 37 | 38 | 39 | /* 40 | * Store 41 | */ 42 | const store = createStore(counterReducer); 43 | 44 | /* 45 | * App Component 46 | */ 47 | class App extends React.Component { 48 | constructor(props) { 49 | super(props); 50 | this.onClick = this.onClick.bind(this); 51 | } 52 | 53 | render() { 54 | 55 | let centerStyle = { 56 | position: 'fixed', 57 | top: '50%', 58 | left: '50%', 59 | transform: 'translate(-50%, -50%)', 60 | WebkitUserSelect: 'none', 61 | MozUserSelect: 'none', 62 | MsUserSelect:'none', 63 | userSelect: 'none', 64 | cursor: 'pointer' 65 | }; 66 | 67 | return ( 68 |
    72 | 73 |

    {this.props.store.getState().value}

    74 |
    75 | ) 76 | } 77 | 78 | onClick() { 79 | this.props.store.dispatch(increase(1)); 80 | } 81 | } 82 | 83 | /* 84 | * Rendering 85 | */ 86 | const render = () => { 87 | 88 | const appElement = document.getElementById('app'); 89 | ReactDOM.render( 90 | , 91 | appElement 92 | ); 93 | }; 94 | 95 | store.subscribe(render); 96 | render(); 97 | -------------------------------------------------------------------------------- /10-redux/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { INCREMENT, DECREMENT, SET_DIFF } from '../actions'; 2 | import { combineReducers } from 'redux'; 3 | 4 | const counterInitialState = { 5 | value: 0, 6 | diff: 1 7 | }; 8 | 9 | const counter = (state = counterInitialState, action) => { 10 | switch(action.type) { 11 | case INCREMENT: 12 | return Object.assign({}, state, { 13 | value: state.value + state.diff 14 | }); 15 | case DECREMENT: 16 | return Object.assign({}, state, { 17 | value: state.value - state.diff 18 | }); 19 | case SET_DIFF: 20 | return Object.assign({}, state, { 21 | diff: action.diff 22 | }); 23 | default: 24 | return state; 25 | } 26 | }; 27 | 28 | 29 | const extra = (state = { value: 'this_is_extra_reducer' }, action) => { 30 | switch(action.type) { 31 | default: 32 | return state; 33 | } 34 | } 35 | 36 | const counterApp = combineReducers({ 37 | counter, 38 | extra 39 | }); 40 | 41 | export default counterApp; 42 | -------------------------------------------------------------------------------- /10-redux/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | entry: './src/index.js', 3 | 4 | output: { 5 | path: __dirname, 6 | filename: 'app.js' 7 | }, 8 | 9 | devServer: { 10 | inline: true, 11 | port: 7777 12 | }, 13 | 14 | module: 15 | { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | loader: 'babel', 20 | exclude: /node_modules/, 21 | query: { 22 | cacheDirectory: true, 23 | presets: ['es2015', 'react'] 24 | } 25 | } 26 | ] 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /11-using-express-hmr/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /11-using-express-hmr/.gitignore: -------------------------------------------------------------------------------- 1 | public/bundle.js 2 | node_modules/** 3 | build/** 4 | -------------------------------------------------------------------------------- /11-using-express-hmr/README.md: -------------------------------------------------------------------------------- 1 | # React-Express-HMR-Example 2 | 3 | ## About 4 | This is an example project that uses React.js on Express.js server. In development environment, webpack-dev-server will be launched together with Express.js server that has Hot Module Replacement enabled using react-hot-loader. 5 | Both of client-side and server-side codes are written in ES6 syntax. 6 | 7 | The port of Express.js server is 3000 and port of webpack-dev-server is 3001. 8 | 9 | ## Installation 10 | ``` 11 | npm install 12 | ``` 13 | 14 | ## Scripts 15 | ### clean 16 | ```bash 17 | # removes build directory and bundle.js 18 | npm run clean 19 | ``` 20 | ### build 21 | ```bash 22 | # transpiles ES6 codes of both client-side and server-side 23 | npm run build 24 | ``` 25 | ### start 26 | ```bash 27 | # starts the server with production environment 28 | npm run start 29 | ``` 30 | ### development 31 | ```bash 32 | # starts the server with development environment 33 | npm run development 34 | ``` 35 | -------------------------------------------------------------------------------- /11-using-express-hmr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-express-hmr", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "clean": "rm -rf build public/bundle.js", 8 | "build": "./node_modules/.bin/babel server --out-dir build && ./node_modules/.bin/webpack", 9 | "start": "NODE_ENV=production node ./build/main.js", 10 | "development": "NODE_ENV=development node ./build/main.js" 11 | }, 12 | "author": "velopert (https://velopert.com)", 13 | "license": "ISC", 14 | "dependencies": { 15 | "express": "^4.13.4", 16 | "react": "^15.0.2", 17 | "react-dom": "^15.0.2" 18 | }, 19 | "devDependencies": { 20 | "babel-cli": "^6.9.0", 21 | "babel-core": "^6.8.0", 22 | "babel-loader": "^6.2.4", 23 | "babel-preset-es2015": "^6.6.0", 24 | "babel-preset-react": "^6.5.0", 25 | "react-hot-loader": "^1.3.0", 26 | "webpack": "^1.13.0", 27 | "webpack-dev-server": "^1.14.1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /11-using-express-hmr/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React App on Express Server 7 | 8 | 9 | 10 |
    11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /11-using-express-hmr/server/main.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import WebpackDevServer from 'webpack-dev-server'; 3 | import webpack from 'webpack'; 4 | 5 | const app = express(); 6 | const port = 3000; 7 | const devPort = 3001; 8 | 9 | 10 | if(process.env.NODE_ENV == 'development') { 11 | console.log('Server is running on development mode'); 12 | 13 | const config = require('../webpack.dev.config'); 14 | let compiler = webpack(config); 15 | let devServer = new WebpackDevServer(compiler, config.devServer); 16 | devServer.listen(devPort, () => { 17 | console.log('webpack-dev-server is listening on port', devPort); 18 | }); 19 | } 20 | app.use('/', express.static(__dirname + '/../public')); 21 | 22 | app.get('/hello', (req, res) => { 23 | return res.send('Can you hear me?'); 24 | }); 25 | 26 | 27 | import posts from './routes/posts'; 28 | app.use('/posts', posts); 29 | 30 | const server = app.listen(port, () => { 31 | console.log('Express listening on port', port); 32 | }); 33 | -------------------------------------------------------------------------------- /11-using-express-hmr/server/routes/posts.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | 3 | const router = express.Router(); 4 | 5 | router.get('/', (req,res) => { 6 | res.send('posts'); 7 | }); 8 | 9 | router.get('/read/:id', (req, res) => { 10 | res.send('You are reading post ' + req.params.id); 11 | }); 12 | 13 | export default router; 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /11-using-express-hmr/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class App extends React.Component { 4 | render() { 5 | return ( 6 |

    This is Hot

    7 | ) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /11-using-express-hmr/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | let rootElement = document.getElementById('root'); 6 | 7 | ReactDOM.render(, rootElement); 8 | 9 | -------------------------------------------------------------------------------- /11-using-express-hmr/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | entry: './src/index.js', 4 | 5 | output: { 6 | path: __dirname + '/public', 7 | filename: 'bundle.js' 8 | }, 9 | 10 | module: { 11 | loaders: [ 12 | { 13 | test: /\.js$/, 14 | loader: 'babel', 15 | exclude: /node_modules/, 16 | query: { 17 | cacheDirectory: true, 18 | presets: ['es2015', 'react'] 19 | } 20 | } 21 | ] 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /11-using-express-hmr/webpack.dev.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | 5 | entry: [ 6 | './src/index.js', 7 | 'webpack-dev-server/client?http://0.0.0.0:3001', 8 | 'webpack/hot/only-dev-server' 9 | ], 10 | 11 | output: { 12 | path: '/', 13 | filename: 'bundle.js' 14 | }, 15 | 16 | devServer: { 17 | hot: true, 18 | filename: 'bundle.js', 19 | publicPath: '/', 20 | historyApiFallback: true, 21 | contentBase: './public', 22 | proxy: { 23 | "*": "http://localhost:3000" 24 | } 25 | }, 26 | 27 | plugins: [ 28 | new webpack.optimize.OccurenceOrderPlugin(), 29 | new webpack.HotModuleReplacementPlugin(), 30 | new webpack.NoErrorsPlugin() 31 | ], 32 | 33 | module: { 34 | loaders: [ 35 | { 36 | test: /\.js$/, 37 | loaders: ['react-hot', 'babel?' + JSON.stringify({ 38 | cacheDirectory: true, 39 | presets: ['es2015', 'react'] 40 | })], 41 | exclude: /node_modules/, 42 | } 43 | ] 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | M# REACT TUTORIALS 2 | 3 | This repository has some sample ReactJS projects that are used from the tutorials in [Velopert Blog](http://velopert.com) (KOREAN) 4 | 5 | 6 | | Directory | Blog Post | 7 | | ------------- |-------------| 8 | | 01-react-tryout| [[React.JS] 강좌 1편 소개 및 맛보기](https://velopert.com/775) | 9 | | 02-environment-setup | [[React.JS] 강좌 2편 작업환경 설정하기](https://velopert.com/814)| 10 | | 03-jsx| [[React.JS] 강좌 3편 JSX](https://velopert.com/867)| 11 | | 04-component | [[React.JS] 강좌 4편 Component 생성 및 모듈화](http://velopert.com/900)| 12 | 13 | # . 14 | --------------------------------------------------------------------------------