├── .gitignore
├── README.md
├── lessons
├── 00-setup
│ ├── App.js
│ ├── index.html
│ ├── instruction.html
│ ├── main.js
│ ├── package.json
│ └── webpack.config.js
├── 01-intro
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 02-render
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 03-properties
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 04-state
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 05-owner-ownee
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 06-refs
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 07-child-properties
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 08-lifecycle-mounting
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 09-lifecycle-mounting-usage
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 10-lifecycle-updates
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 11-higher-order
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 12-composable
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 13-dynamic
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 14-build-compiler
│ ├── App.js
│ ├── index.html
│ ├── main.js
│ └── style.css
├── 15-jsx
│ └── index.html
├── 16-precompile
│ ├── dist.js
│ ├── index.html
│ ├── src.js
│ └── style.css
├── 17-integration
│ ├── App.js
│ ├── index.html
│ └── main.js
├── 18-devtools
│ ├── App.js
│ ├── index.html
│ └── main.js
├── cloneElement
│ ├── App.js
│ ├── index.html
│ └── main.js
├── events
│ ├── App.js
│ ├── index.html
│ └── main.js
├── index.html
├── prop-validation
│ ├── App.js
│ ├── index.html
│ └── main.js
└── react-children
│ ├── App.js
│ ├── index.html
│ └── main.js
├── package.json
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ```bash
2 | npm install
3 | npm start
4 | ```
5 |
6 | open browser to http://localhost:3000
7 |
--------------------------------------------------------------------------------
/lessons/00-setup/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | class App extends React.Component {
3 | render(){
4 | return
Hi
5 | }
6 | }
7 |
8 | export default App
9 |
--------------------------------------------------------------------------------
/lessons/00-setup/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Setup
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/00-setup/instruction.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 | index.html
10 |
11 | <!DOCTYPE html>
12 | <html lang="en">
13 | <head>
14 | <meta charset="UTF-8">
15 | <title>Setup</title>
16 | </head>
17 | <body>
18 | <div id="app"></div>
19 | <script src="index.js"></script>
20 | </body>
21 | </html>
22 |
23 | package.json
24 |
25 | {
26 | "name": "es6-react-setup",
27 | "version": "1.0.0",
28 | "main": "index.js",
29 | "scripts": {
30 | "start": "webpack-dev-server"
31 | },
32 | "author": "",
33 | "license": "ISC",
34 | "dependencies": {
35 | "babel-core": "^6.2.1",
36 | "babel-loader": "^6.2.0",
37 | "babel-preset-es2015": "^6.1.18",
38 | "babel-preset-react": "^6.1.18",
39 | "react": "^0.14.3",
40 | "react-dom": "^0.14.3"
41 | },
42 | "description": "Setup files for React in ES6 lessons"
43 | }
44 |
45 | webpack.config.js
46 |
47 | module.exports = {
48 | entry: './main.js',
49 | output: {
50 | path: './',
51 | filename: 'index.js'
52 | },
53 | devServer: {
54 | inline: true,
55 | port: 3333
56 | },
57 | module: {
58 | loaders: [
59 | {
60 | test: /\.js$/,
61 | exclude: /node_modules/,
62 | loader: 'babel',
63 | query: {
64 | presets: ['es2015', 'react']
65 | }
66 | }
67 | ]
68 | }
69 | }
70 |
71 |
72 | App.js
73 |
74 | import React from 'react';
75 | class App extends React.Component {
76 | render(){
77 | return <div>Hi</div>
78 | }
79 | }
80 |
81 | export default App
82 |
83 | main.js
84 |
85 | import React from 'react';
86 | import ReactDOM from 'react-dom';
87 | import App from './App';
88 | ReactDOM.render(<App />, document.getElementById('app'))
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/lessons/00-setup/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'))
5 |
--------------------------------------------------------------------------------
/lessons/00-setup/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "es6-react-setup",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "scripts": {
6 | "start": "webpack-dev-server"
7 | },
8 | "author": "",
9 | "license": "ISC",
10 | "dependencies": {
11 | "babel-core": "^6.2.1",
12 | "babel-loader": "^6.2.0",
13 | "babel-preset-es2015": "^6.1.18",
14 | "babel-preset-react": "^6.1.18",
15 | "react": "^0.14.3",
16 | "react-dom": "^0.14.3"
17 | },
18 | "description": "Setup files for React in ES6 lessons"
19 | }
20 |
--------------------------------------------------------------------------------
/lessons/00-setup/webpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | entry: './main.js',
3 | output: {
4 | path: './',
5 | filename: 'index.js'
6 | },
7 | devServer: {
8 | inline: true,
9 | port: 3333
10 | },
11 | module: {
12 | loaders: [
13 | {
14 | test: /\.js$/,
15 | exclude: /node_modules/,
16 | loader: 'babel',
17 | query: {
18 | presets: ['es2015', 'react']
19 | }
20 | }
21 | ]
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lessons/01-intro/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/bakoniw/2/
2 |
3 | import React from 'react';
4 |
5 | class App extends React.Component {
6 | render(){
7 | return Hello Series
8 | }
9 | }
10 |
11 | //const App = () => Hello stateless
12 |
13 | export default App
14 |
--------------------------------------------------------------------------------
/lessons/01-intro/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 01
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/01-intro/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/02-render/App.js:
--------------------------------------------------------------------------------
1 | //https://jsbin.com/mezuno/edit?js,output
2 |
3 | import React from 'react';
4 |
5 | class App extends React.Component {
6 | render(){
7 | return (
8 |
9 |
Hello World
10 | Bold
11 |
12 | );
13 | }
14 | }
15 |
16 | export default App
17 |
--------------------------------------------------------------------------------
/lessons/02-render/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 02
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/02-render/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/03-properties/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/yirifo/edit?html,js,output
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 | import PropTypes from 'prop-types'
6 |
7 | class App extends React.Component {
8 | render(){
9 | let txt = this.props.txt
10 | return {txt}
11 | }
12 | }
13 | App.propTypes = {
14 | txt: PropTypes.string,
15 | cat: PropTypes.number.isRequired
16 | }
17 | App.defaultProps ={
18 | txt: 'this is the default txt'
19 | }
20 | ReactDOM.render(
21 | ,
22 | document.getElementById('app')
23 | );
24 |
--------------------------------------------------------------------------------
/lessons/03-properties/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 03
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/03-properties/main.js:
--------------------------------------------------------------------------------
1 | import App from './App';
2 |
--------------------------------------------------------------------------------
/lessons/04-state/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/zijoxu/edit?js,output
2 |
3 | import React from 'react';
4 |
5 | class App extends React.Component {
6 | constructor(){
7 | super();
8 | this.state = {
9 | txt: 'this is the state txt',
10 | cat: 0
11 | }
12 | }
13 | update(e){
14 | this.setState({txt: e.target.value})
15 | }
16 | render(){
17 | return (
18 |
19 |
21 |
{this.state.txt} - {this.state.cat}
22 |
23 | )
24 | }
25 | }
26 |
27 | export default App
28 |
--------------------------------------------------------------------------------
/lessons/04-state/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 01
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/04-state/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/05-owner-ownee/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/sokoje/2/edit
2 |
3 | import React from 'react';
4 |
5 | class App extends React.Component {
6 | constructor(){
7 | super();
8 | this.state = {
9 | txt: 'this is the state text'
10 | }
11 | }
12 | update(e){
13 | this.setState({txt: e.target.value})
14 | }
15 | render(){
16 | return (
17 |
18 |
{this.state.txt}
19 |
20 |
21 |
22 |
23 | )
24 | }
25 | }
26 |
27 | const Widget = (props) =>
28 |
29 |
30 | export default App
31 |
--------------------------------------------------------------------------------
/lessons/05-owner-ownee/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 01
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/05-owner-ownee/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/06-refs/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/jilucuw/1/edit
2 |
3 | import React from 'react';
4 |
5 | class App extends React.Component {
6 | constructor(){
7 | super();
8 | this.state = {a: '', b: ''}
9 | }
10 | update(){
11 | this.setState({
12 | a: this.a.refs.input.value,
13 | b: this.refs.b.value
14 | })
15 | }
16 | render(){
17 | return (
18 |
19 | this.a = component}
21 | update={this.update.bind(this)}
22 | /> {this.state.a}
23 |
24 | {this.state.b}
29 |
30 | )
31 | }
32 | }
33 |
34 | class Input extends React.Component {
35 | render(){
36 | return
37 | }
38 | }
39 |
40 | export default App
41 |
--------------------------------------------------------------------------------
/lessons/06-refs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 01
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/06-refs/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/07-child-properties/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/cumopab/edit?js,output
2 |
3 | import React from 'react';
4 |
5 | class App extends React.Component {
6 | render(){
7 | return
8 | }
9 | }
10 |
11 | const Button = (props) =>
12 |
13 |
14 | class Heart extends React.Component {
15 | render(){
16 | return ♥
17 | }
18 | }
19 |
20 | export default App
21 |
--------------------------------------------------------------------------------
/lessons/07-child-properties/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 07
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/lessons/07-child-properties/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/08-lifecycle-mounting/App.js:
--------------------------------------------------------------------------------
1 | // problematic in JsBin
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 |
6 | class App extends React.Component {
7 | constructor(){
8 | super();
9 | this.state = { val: 0 };
10 | this.update = this.update.bind(this);
11 | }
12 | update(){
13 | this.setState({val: this.state.val + 1 })
14 | }
15 | componentWillMount(){
16 | console.log('componentWillMount')
17 | }
18 | render(){
19 | console.log('render')
20 | return
21 | }
22 | componentDidMount(){
23 | console.log('componentDidMount')
24 | }
25 | componentWillUnmount(){
26 | console.log('componentWillUnmount')
27 | }
28 | }
29 |
30 | class Wrapper extends React.Component {
31 | constructor(){
32 | super();
33 | }
34 | mount(){
35 | ReactDOM.render(, document.getElementById('a'))
36 | }
37 | unmount(){
38 | ReactDOM.unmountComponentAtNode(document.getElementById('a'))
39 | }
40 | render(){
41 | return (
42 |
43 |
44 |
45 |
46 |
47 | )
48 | }
49 | }
50 |
51 |
52 | export default Wrapper
53 |
--------------------------------------------------------------------------------
/lessons/08-lifecycle-mounting/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 08
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/08-lifecycle-mounting/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/09-lifecycle-mounting-usage/App.js:
--------------------------------------------------------------------------------
1 | // problematic in JsBin
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 |
6 | class App extends React.Component {
7 | constructor(){
8 | super();
9 | this.state = { val: 0 };
10 | this.update = this.update.bind(this);
11 | }
12 | update(){
13 | this.setState({val: this.state.val + 1 })
14 | }
15 | componentWillMount(){
16 | console.log('componentWillMount')
17 | this.setState({m: 2})
18 | }
19 | render(){
20 | console.log('render')
21 | return (
22 |
25 | )
26 | }
27 | componentDidMount(){
28 | console.log('componentDidMount')
29 | this.inc = setInterval(this.update,500)
30 | }
31 | componentWillUnmount(){
32 | console.log('componentWillUnmount');
33 | clearInterval(this.inc)
34 | }
35 | }
36 |
37 | class Wrapper extends React.Component {
38 | constructor(){
39 | super();
40 | }
41 | mount(){
42 | ReactDOM.render(, document.getElementById('a'))
43 | }
44 | unmount(){
45 | ReactDOM.unmountComponentAtNode(document.getElementById('a'))
46 | }
47 | render(){
48 | return (
49 |
50 |
51 |
52 |
53 |
54 | )
55 | }
56 | }
57 |
58 |
59 | export default Wrapper
60 |
--------------------------------------------------------------------------------
/lessons/09-lifecycle-mounting-usage/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 09
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/09-lifecycle-mounting-usage/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/10-lifecycle-updates/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/deliwe/edit?js,console,output
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 |
6 | class App extends React.Component {
7 | constructor(){
8 | super();
9 | this.state = {increasing: false}
10 | }
11 | update(){
12 | ReactDOM.render(
13 | ,
14 | document.getElementById('root'))
15 | }
16 | componentWillReceiveProps(nextProps){
17 | this.setState({increasing: nextProps.val > this.props.val})
18 | }
19 | shouldComponentUpdate(nextProps, nextState) {
20 | return nextProps.val % 5 === 0;
21 | }
22 | render(){
23 | console.log(this.state.increasing)
24 | return (
25 |
28 | )
29 | }
30 | componentDidUpdate(prevProps, prevState) {
31 | console.log(`prevProps: ${prevProps.val}`)
32 | }
33 | }
34 |
35 | App.defaultProps = {val: 0}
36 |
37 | export default App
38 |
--------------------------------------------------------------------------------
/lessons/10-lifecycle-updates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 10
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/10-lifecycle-updates/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('root'));
5 |
--------------------------------------------------------------------------------
/lessons/11-higher-order/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/boxoso/edit?js,output
2 |
3 | import React from 'react';
4 |
5 | const HOC = (InnerComponent) => class extends React.Component {
6 | constructor(){
7 | super();
8 | this.state = {count: 0}
9 | }
10 | update(){
11 | this.setState({count: this.state.count + 1})
12 | }
13 | componentWillMount(){
14 | console.log('will mount')
15 | }
16 | render(){
17 | return (
18 |
23 | )
24 | }
25 | }
26 |
27 | class App extends React.Component {
28 | render(){
29 | return (
30 |
31 |
32 |
33 | label
34 |
35 | )
36 | }
37 | }
38 |
39 | const Button = HOC((props) =>
40 |
41 | )
42 |
43 | class Label extends React.Component {
44 | componentWillMount(){
45 | console.log('label will mount')
46 | }
47 | render(){
48 | return (
49 |
52 | )
53 | }
54 | }
55 |
56 | const LabelHOC = HOC(Label)
57 |
58 | export default App
59 |
--------------------------------------------------------------------------------
/lessons/11-higher-order/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 11
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/11-higher-order/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/12-composable/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/yiboxe/edit?js,output
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 | class App extends React.Component {
6 | constructor(){
7 | super();
8 | this.state = {
9 | red: 0
10 | }
11 | this.update = this.update.bind(this)
12 | }
13 | update(e){
14 | this.setState({
15 | red: ReactDOM.findDOMNode(this.refs.red.refs.inp).value
16 | })
17 | }
18 | render(){
19 | return (
20 |
21 |
29 |
30 | );
31 | }
32 | }
33 |
34 | class NumInput extends React.Component {
35 | render(){
36 | let label = this.props.label !== '' ?
37 | : ''
38 | return (
39 |
40 |
47 | {label}
48 |
49 | );
50 | }
51 | }
52 |
53 | NumInput.propTypes = {
54 | min: React.PropTypes.number,
55 | max: React.PropTypes.number,
56 | step: React.PropTypes.number,
57 | val: React.PropTypes.number,
58 | label: React.PropTypes.string,
59 | update: React.PropTypes.func.isRequired,
60 | type: React.PropTypes.oneOf(['number', 'range'])
61 | }
62 |
63 | NumInput.defaultProps = {
64 | min: 0,
65 | max: 0,
66 | step: 1,
67 | val: 0,
68 | label: '',
69 | type: 'range'
70 | }
71 |
72 |
73 | export default App
74 |
--------------------------------------------------------------------------------
/lessons/12-composable/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 12
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/12-composable/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/13-dynamic/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/qubonu/1/edit?js,output
2 | import React from 'react';
3 | class App extends React.Component {
4 | constructor(){
5 | super();
6 | this.state = {items: []}
7 | }
8 | componentWillMount(){
9 | fetch( 'https://swapi.co/api/people/?format=json' )
10 | .then( response => response.json() )
11 | .then( ({results: items}) => this.setState({items}))
12 | }
13 | filter(e){
14 | this.setState({filter: e.target.value})
15 | }
16 | render(){
17 | let items = this.state.items;
18 | if(this.state.filter){
19 | items = items.filter( item =>
20 | item.name.toLowerCase()
21 | .includes(this.state.filter.toLowerCase()))
22 | }
23 | return (
24 |
25 |
27 | {items.map(item =>
28 |
)}
29 |
30 | )
31 | }
32 | }
33 |
34 | const Person = (props) => {props.person.name}
35 |
36 | export default App
37 |
--------------------------------------------------------------------------------
/lessons/13-dynamic/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 13
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/13-dynamic/main.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/qubonu/edit?js,output
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 | import App from './App';
6 | ReactDOM.render(, document.getElementById('app'));
7 |
--------------------------------------------------------------------------------
/lessons/14-build-compiler/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/qonaga/edit?js,output
2 |
3 | import React from 'react';
4 |
5 | class App extends React.Component {
6 | constructor(){
7 | super();
8 | this.state = {
9 | input: '/* add your jsx here */',
10 | output: '',
11 | err: ''
12 | }
13 | }
14 | update(e){
15 | let code = e.target.value;
16 | try {
17 | this.setState({
18 | output: window.Babel
19 | .transform(code, { presets: ['es2015', 'react']})
20 | .code,
21 | err: ''
22 | })
23 | }
24 | catch(err){
25 | this.setState({err: err.message})
26 | }
27 | }
28 | render(){
29 | return (
30 |
41 | )
42 | }
43 | }
44 |
45 | export default App
46 |
--------------------------------------------------------------------------------
/lessons/14-build-compiler/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 14
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/lessons/14-build-compiler/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/14-build-compiler/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: monospace;
5 | }
6 |
7 | header {
8 | display: block;
9 | height: 5vh;
10 | overflow: auto;
11 | background-color: pink;
12 | color: red;
13 | font-size: 28px
14 | }
15 |
16 | .container {
17 | height: 95vh;
18 | display:flex;
19 | }
20 |
21 | pre {
22 | background-color: #f8f8f8;
23 | }
24 |
25 | pre, textarea {
26 | width: 50%;
27 | font-family: monospace;
28 | font-size: 28px;
29 | margin: 0;
30 | padding: 10px;
31 | color: #222;
32 | }
33 |
34 | textarea:focus {outline: 0;}
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/lessons/15-jsx/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSX
6 |
7 |
8 |
9 | //lowercase !== React.Component
10 | <div></div>
11 |
12 | //Uppercase === React.Component reference
13 | <App></App>
14 |
15 | //self closing tags
16 | <div />
17 |
18 | //multiple nodes == returning multiple functions :(
19 | <div></div>
20 | <a></a>
21 |
22 |
23 | //single node == returning single function :)
24 | <div>
25 | <a></a>
26 | </div>
27 |
28 |
29 | //second argument == component props,functions, etc.
30 | <div>
31 | <a href="#"></a>
32 | </div>
33 |
34 |
35 | //additional arguments == children
36 | <div>
37 | <a href="#">this is the text</a>
38 | </div>
39 |
40 |
41 | //React will not render unknown attributes
42 | //to the browser without data-*
43 | <div notrendered="x" data-rendered="x">
44 | <a href="#">this is the text</a>
45 | </div>
46 |
47 |
48 | //interpreted
49 | <div notrendered="x" data-rendered="x">
50 | <a href="#" onClick={this.update}>
51 | {/* this is a comment */}
52 | this is the text
53 | </a>
54 | </div>
55 |
56 |
57 | //if else is no good in JSX syntax, use a ternary expression
58 | <div notrendered="x" data-rendered="x">
59 | <a href="#" onClick={this.update}>this is the text</a>
60 | {i>1 ? 'More than one' : 'One'}
61 | {i>1 && 'More than one'}
62 | {/* this is a comment */}
63 | </a>
64 | </div>
65 |
66 |
67 |
68 | //inline styles
69 | var myStyle={
70 | backgroundColor:'#000',
71 | height:10 //no need for 'px'
72 | }
73 | <div style={myStyle} notrendered="x" data-rendered="x">
74 | <a href="#" onClick={this.update}>this.props.children</a>
75 | {i>1 ? 'More than one' : 'One'}
76 | {i>1 && 'More than one'}
77 | {/* this is a comment */}
78 | </a>
79 | </div>
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/lessons/16-precompile/dist.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const App = () => {
4 | return React.createElement(
5 | "div",
6 | null,
7 | React.createElement(
8 | "table",
9 | null,
10 | React.createElement(
11 | "thead",
12 | null,
13 | React.createElement(
14 | "tr",
15 | null,
16 | React.createElement(
17 | "th",
18 | null,
19 | "heading"
20 | ),
21 | React.createElement(
22 | "th",
23 | null,
24 | "heading"
25 | ),
26 | React.createElement(
27 | "th",
28 | null,
29 | "heading"
30 | )
31 | )
32 | ),
33 | React.createElement(
34 | "tbody",
35 | null,
36 | React.createElement(
37 | "tr",
38 | { id: "theRow" },
39 | React.createElement(
40 | "td",
41 | null,
42 | React.createElement("form", { action: "" })
43 | )
44 | )
45 | )
46 | )
47 | );
48 | };
49 |
--------------------------------------------------------------------------------
/lessons/16-precompile/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 16 - precompile
6 |
7 |
8 |
9 |
10 |
11 | "use strict"
12 |
13 | const App = () => {
14 | return (
15 | <div>
16 | <table>
17 | <thead>
18 | <tr>
19 | <th>heading</th>
20 | <th>heading</th>
21 | <th>heading</th>
22 | </tr>
23 | </thead>
24 | <tbody>
25 | <tr id="theRow">
26 | <td>
27 | <form action=""></form>
28 | </td>
29 | </tr>
30 | </tbody>
31 | </table>
32 | </div>
33 | );
34 | }
35 |
36 |
37 | "use strict";
38 |
39 | const App = () => {
40 | return React.createElement(
41 | "div",
42 | null,
43 | React.createElement(
44 | "table",
45 | null,
46 | React.createElement(
47 | "thead",
48 | null,
49 | React.createElement(
50 | "tr",
51 | null,
52 | React.createElement(
53 | "th",
54 | null,
55 | "heading"
56 | ),
57 | React.createElement(
58 | "th",
59 | null,
60 | "heading"
61 | ),
62 | React.createElement(
63 | "th",
64 | null,
65 | "heading"
66 | )
67 | )
68 | ),
69 | React.createElement(
70 | "tbody",
71 | null,
72 | React.createElement(
73 | "tr",
74 | { id: "theRow" },
75 | React.createElement(
76 | "td",
77 | null,
78 | React.createElement("form", { action: "" })
79 | )
80 | )
81 | )
82 | )
83 | );
84 | };
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/lessons/16-precompile/src.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | const App = () => {
4 | return (
5 |
6 |
7 |
8 |
9 | heading |
10 | heading |
11 | heading |
12 |
13 |
14 |
15 |
16 |
17 |
18 | |
19 |
20 |
21 |
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/lessons/16-precompile/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | }
5 |
6 | .container {
7 | height: 100vh;
8 | display:flex;
9 | }
10 |
11 | pre {
12 | border:1px solid #ccc;
13 | }
14 |
15 | pre {
16 | width: 50%;
17 | font-family: monospace;
18 | font-size: 14px;
19 | margin: 0;
20 | padding: 10px;
21 | color: #222;
22 | }
23 |
--------------------------------------------------------------------------------
/lessons/17-integration/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import * as d3 from 'd3';
4 |
5 | class Chart extends React.Component {
6 | render(){
7 | return
8 | }
9 | renderChart(){
10 | d3.select(this.refs.chartArea).selectAll('div')
11 | .data(this.props.data)
12 | .enter()
13 | .append('div')
14 | .attr('class', 'bar')
15 | .style('height', function (d) {
16 | return d * 5 + 'px';
17 | });
18 | }
19 | componentDidMount(){
20 | this.renderChart()
21 | }
22 | }
23 |
24 | class App extends React.Component {
25 | makeData(){
26 | return Array.from(new Array(5), () => Math.floor((Math.random() * 15) + 1))
27 | }
28 | render(){
29 | return (
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | )
38 | }
39 | }
40 |
41 | export default App
42 |
--------------------------------------------------------------------------------
/lessons/17-integration/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 17
6 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/lessons/17-integration/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/18-devtools/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | class App extends React.Component {
4 | constructor(){
5 | super();
6 | this.state = {
7 | pages: [
8 | { title: 'Home' },
9 | { title: 'About' },
10 | { title: 'Contact' }
11 | ],
12 | index: 0
13 | }
14 | }
15 | changePage(index){
16 | this.setState({index})
17 | }
18 | render(){
19 | let title = this.state.pages[this.state.index].title;
20 | return (
21 |
22 |
26 |
27 |
28 |
29 | );
30 | }
31 | }
32 |
33 | const Header = (props) => {
34 | return (
35 |
36 | The {props.title.toUpperCase()} Page
37 |
38 | );
39 | }
40 |
41 | const Nav = (props) => {
42 | let items = props.items.map((item, i) => {
43 | return
44 | })
45 | return
46 | }
47 |
48 | const NavItem = (props) => {
49 | return (
50 |
51 |
54 | {props.items[props.index].title}
55 |
56 |
57 | )
58 | }
59 |
60 | const Content = (props) => {props.title}
61 |
62 | export default App
63 |
64 |
65 | // tests go here.
66 |
--------------------------------------------------------------------------------
/lessons/18-devtools/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 08
6 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/lessons/18-devtools/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/cloneElement/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | class App extends React.Component {
4 | render(){
5 | return (
6 |
7 |
8 |
9 |
10 |
11 | )
12 | }
13 | }
14 |
15 |
16 | class Buttons extends React.Component {
17 | constructor(){
18 | super();
19 | this.state = {selected: 'None'}
20 | }
21 | selectItem(selected){
22 | this.setState({selected})
23 | }
24 | render(){
25 | let fn = child =>
26 | React.cloneElement(child, {
27 | onClick:this.selectItem.bind(this, child.props.value)
28 | })
29 | let items = React.Children.map(this.props.children, fn);
30 | return (
31 |
32 |
You have selected: {this.state.selected}
33 | {items}
34 |
35 | )
36 | }
37 | }
38 |
39 | export default App
40 |
--------------------------------------------------------------------------------
/lessons/cloneElement/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | react-children
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/cloneElement/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/events/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | class App extends React.Component {
4 | constructor(){
5 | super();
6 | this.state = {currentEvent: '---'}
7 | this.update = this.update.bind(this)
8 | }
9 | update(e){
10 | this.setState({currentEvent: e.type})
11 | }
12 | render(){
13 | return (
14 |
15 |
28 |
{this.state.currentEvent}
29 |
30 | )
31 | }
32 | }
33 |
34 | export default App
35 |
--------------------------------------------------------------------------------
/lessons/events/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | react-children
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/events/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | React ES6
6 |
12 |
13 |
14 |
15 |
16 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/lessons/prop-validation/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/yurokoy/1/edit
2 |
3 | import React from 'react';
4 |
5 | class App extends React.Component {
6 | render(){
7 | return
8 | }
9 | }
10 |
11 | const Title = (props) => Title: {props.text}
12 |
13 | Title.propTypes = {
14 | text(props, propName, component){
15 | if(!(propName in props)){
16 | return new Error(`missing ${propName}`)
17 | }
18 | if(props[propName].length < 6){
19 | return new Error(`${propName} was too short`)
20 | }
21 | }
22 | }
23 |
24 | export default App
25 |
--------------------------------------------------------------------------------
/lessons/prop-validation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Lesson 13
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/prop-validation/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/lessons/react-children/App.js:
--------------------------------------------------------------------------------
1 | // https://jsbin.com/qiwesa/1/edit
2 |
3 | import React from 'react';
4 |
5 | class App extends React.Component {
6 | render(){
7 | return (
8 |
9 |
10 |
11 | )
12 | }
13 | }
14 |
15 | class Parent extends React.Component {
16 | render(){
17 | //console.log(this.props.children)
18 | // let items = React.Children
19 | // .forEach(this.props.children,
20 | // child => console.log(child.props.className))
21 | //let items = React.Children.toArray(this.props.children)
22 | let items = React.Children.only(this.props.children)
23 | console.log(items)
24 | return null
25 | }
26 | }
27 |
28 | export default App
29 |
--------------------------------------------------------------------------------
/lessons/react-children/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | react-children
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lessons/react-children/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | ReactDOM.render(, document.getElementById('app'));
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "egghead-react-es6",
3 | "version": "1.0.0",
4 | "description": "React Fundamentals in ES6",
5 | "main": "server.js",
6 | "dependencies": {
7 | "babel-core": "^6.24.1",
8 | "babel-loader": "^6.4.1",
9 | "babel-preset-es2015": "^6.24.1",
10 | "babel-preset-react": "^6.24.1",
11 | "d3": "^4.7.4",
12 | "prop-types": "^15.5.8",
13 | "react": "^15.5.4",
14 | "react-dom": "^15.5.4",
15 | "webpack": "^2.4.0",
16 | "webpack-dev-server": "^2.4.2"
17 | },
18 | "devDependencies": {},
19 | "scripts": {
20 | "start": "webpack-dev-server"
21 | },
22 | "author": "Joe Maddalone",
23 | "license": "ISC"
24 | }
25 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var port = process.env.PORT || 3000;
2 |
3 | var lessons = [
4 | "01-intro",
5 | "02-render",
6 | "03-properties",
7 | "04-state",
8 | "05-owner-ownee",
9 | "06-refs",
10 | "07-child-properties",
11 | "08-lifecycle-mounting",
12 | "09-lifecycle-mounting-usage",
13 | "10-lifecycle-updates",
14 | "11-higher-order",
15 | "12-composable",
16 | "13-dynamic",
17 | "14-build-compiler",
18 | "17-integration",
19 | "18-devtools",
20 | "prop-validation",
21 | "react-children",
22 | "cloneElement",
23 | "events"
24 | ]
25 |
26 | var entry = {}
27 | lessons.forEach(function(lesson){
28 | entry[lesson] = './lessons/' + lesson + '/main.js'
29 | })
30 |
31 | module.exports = {
32 | entry: entry,
33 | output: {
34 | path: __dirname + './lessons/',
35 | filename: "[name]/index.js",
36 | publicPath: '/'
37 | },
38 | devServer: {
39 | inline: true,
40 | contentBase: './lessons/',
41 | port: port
42 | },
43 | module: {
44 | rules: [
45 | {
46 | test: /\.jsx?$/,
47 | exclude: /(node_modules|bower_components)/,
48 | loader: 'babel-loader',
49 | query: {
50 | presets: ['es2015', 'react']
51 | }
52 | }
53 | ]
54 | }
55 | };
56 |
--------------------------------------------------------------------------------