├── .gitignore ├── LICENSE ├── README.md ├── ch2 ├── 2-1.json ├── 2-10.html ├── 2-11.html ├── 2-2.html ├── 2-3.html ├── 2-4.html ├── 2-5.html ├── 2-6.html ├── 2-7.html ├── 2-8.html └── 2-9.html ├── ch3 ├── 3-1.js ├── 3-2.js ├── 3-3.js ├── 3-4.js ├── 3-5.js ├── 3-6.js ├── 3-7.js └── 3-8.js ├── ch4 ├── 4-1.js ├── 4-10.js ├── 4-11.js ├── 4-12.js ├── 4-13.js ├── 4-2.js ├── 4-3.js ├── 4-4.js ├── 4-5.js ├── 4-6.js ├── 4-7.js ├── 4-8.js └── 4-9.js └── ch5 └── 5-1.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 React in Action 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # code 2 | Code listings for React in Action 3 | -------------------------------------------------------------------------------- /ch2/2-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 123, 3 | "content": "What we hope ever to do with ease, we must first learn to do with diligence. — Samuel Johnson", 4 | "user": "Mark Thomas", 5 | "comments": [{ 6 | "id": 0, 7 | "user": "David", 8 | "content": "such. win." 9 | }, { 10 | "id": 1, 11 | "user": "Peter", 12 | "content": "Who was Samuel Johnson?" 13 | }, { 14 | "id": 2, 15 | "user": "Mitchell", 16 | "content": "@Peter get off Letters and do your homework!" 17 | }, { 18 | "id": 3, 19 | "user": "Peter", 20 | "content": "@mitchell ok dad :P" 21 | }] 22 | } 23 | -------------------------------------------------------------------------------- /ch2/2-10.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React In Action 6 | 7 | 8 | 9 |
10 | 11 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /ch2/2-11.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React In Action 6 | 7 | 8 | 9 | 10 |
11 | 12 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /ch2/2-2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React In Action 6 | 7 | 8 | 9 |
10 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ch2/2-3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React In Action 7 | 8 | 9 | 10 | 11 |
12 | 13 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ch2/2-4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React In Action 7 | 8 | 9 | 10 | 11 |
12 | 13 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ch2/2-5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React In Action 7 | 8 | 9 | 10 | 11 |
12 | 13 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /ch2/2-6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React In Action 7 | 8 | 9 | 10 | 11 |
12 | 13 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ch2/2-7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React In Action 7 | 8 | 9 | 10 | 11 |
12 | 13 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /ch2/2-8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React In Action 7 | 8 | 9 | 10 | 11 |
12 | 13 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /ch2/2-9.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React In Action 7 | 8 | 9 | 10 | 11 |
12 | 13 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /ch3/3-1.js: -------------------------------------------------------------------------------- 1 | const letters = 'Letters'; 2 | const splitLetters = letters.split(''); 3 | console.log("Let's spell a word!"); 4 | splitLetters.forEach(letter => console.log(letter)); 5 | -------------------------------------------------------------------------------- /ch3/3-2.js: -------------------------------------------------------------------------------- 1 | // `This` will refer to the global object 2 | console.log(Object.keys(this)); 3 | 4 | // How many keys are there on the global object? 5 | console.log(Object.keys(window).length) 6 | 7 | // in node.js 8 | console.log(Object.keys(global).length) 9 | -------------------------------------------------------------------------------- /ch3/3-3.js: -------------------------------------------------------------------------------- 1 | // when not logged in 2 | let user = null; 3 | 4 | // Load user data from somewhere using the new fetch API 5 | // (essentially the newer, better version of XMLHttpRequest) 6 | 7 | fetch(someUrl) 8 | .then(response => user = response.json()) 9 | .catch(err => console.error(err)); 10 | 11 | // when logged in 12 | console.log(user); 13 | // yields: 14 | // { 15 | // username: 'mark', 16 | // email: 'mark@ifelse.io' 17 | // firstName: 'Mark', 18 | // lastName: 'Thomas', 19 | // preferences: { 20 | // email: false, 21 | // react: true, 22 | // } 23 | // } 24 | 25 | // Change user settings; bring on the emails! 26 | user.preferences.email = true; 27 | 28 | // Update user settings 29 | application.updateUser(user); 30 | 31 | // Perform some logout action 32 | application.logout = function() { 33 | user = null 34 | }; 35 | 36 | application.logout(); 37 | -------------------------------------------------------------------------------- /ch3/3-4.js: -------------------------------------------------------------------------------- 1 | const ShallowMerge = React.createClass({ 2 | getInitialState: function() { 3 | return { 4 | user: { 5 | name: 'Mark', 6 | colors: { 7 | favorite: '' 8 | } 9 | } 10 | }; 11 | }, 12 | onButtonClick: function() { 13 | this.setState({ 14 | user: { 15 | colors: { 16 | favorite: 'blue' 17 | } 18 | } 19 | }); 20 | }, 21 | render: function() { 22 | return ( 23 |
24 |

My favorite color is {this.state.user.colors.favorite} 25 | and my name is 26 |

27 | 28 |
29 | ) 30 | } 31 | }) 32 | 33 | ReactDOM.render( 34 | , 35 | document.getElementById('container') 36 | ); 37 | -------------------------------------------------------------------------------- /ch3/3-5.js: -------------------------------------------------------------------------------- 1 | const Counter = React.createClass({ 2 | getInitialState: function() { 3 | return { 4 | count: 0 5 | }; 6 | }, 7 | onButtonClick: function() { 8 | this.setState(function(previousState, currentProps) { 9 | return { 10 | count: previousState.count + currentProps.incrementBy 11 | }; 12 | }); 13 | }, 14 | render: function() { 15 | return ( 16 |
17 |

{this.state.count}

18 | 19 |
20 | ) 21 | } 22 | }) 23 | 24 | ReactDOM.render( 25 | , 26 | document.getElementById('container') 27 | ); 28 | -------------------------------------------------------------------------------- /ch3/3-6.js: -------------------------------------------------------------------------------- 1 | const Counter = React.createClass({ 2 | propTypes: { 3 | incrementBy: React.PropTypes.number, 4 | name: React.PropTypes.string, 5 | counterStyle: React.PropTypes.shape({ 6 | color: React.PropTypes.string, 7 | fontSize: React.PropTypes.number 8 | }), 9 | onIncrement: React.PropTypes.func.isRequired, 10 | 11 | }, 12 | getDefaultProps: function() { 13 | return {incrementBy: 1}; 14 | }, 15 | getInitialState: function() { 16 | return {count: 0} 17 | }, 18 | onButtonClick: function() { 19 | this.setState(function(previousState, currentProps) { 20 | return { 21 | count: previousState.count + currentProps.incrementBy 22 | }; 23 | }); 24 | }, 25 | render: function() { 26 | // this.props.incrementBy = 2; 27 | return ( 28 |
29 |

{this.state.count}

30 | 31 |
32 | ) 33 | } 34 | }) 35 | 36 | ReactDOM.render( 37 | , 38 | document.getElementById('container') 39 | ); 40 | -------------------------------------------------------------------------------- /ch3/3-7.js: -------------------------------------------------------------------------------- 1 | function Greeting(props) { 2 | return
Hello {props.for}!
; 3 | } 4 | 5 | Greeting.propTypes = { 6 | for: React.PropTypes.string.isRequired 7 | }; 8 | 9 | Greeting.defaultProps = { 10 | for: 'hi' 11 | }; 12 | 13 | ReactDOM.render(, mountNode); 14 | 15 | // Or using the ES6 arrow syntax 16 | 17 | const Greeting = (props) =>
Hello {props.for}
; 18 | //... specify props and default props same as above 19 | 20 | ReactDOM.render(, mountNode); 21 | -------------------------------------------------------------------------------- /ch3/3-8.js: -------------------------------------------------------------------------------- 1 | const UserProfile = (props) => { 2 | return (); 3 | }; 4 | UserProfile.propTypes = { 5 | pagename: React.PropTypes.string 6 | }; 7 | 8 | UserProfile.defaultProps = { 9 | pagename: 'Mark' 10 | }; 11 | 12 | const UserProfileLink = (props) => { 13 | return ( 14 | 15 | {this.props.username} 16 | 17 | ); 18 | }; 19 | 20 | const UserCard = (props) => { 21 | #C 22 | return ( 23 |
24 | 25 | 26 |
27 | ); 28 | }; 29 | 30 | ReactDOM.render( 31 | , 32 | document.getElementById('container') 33 | ); 34 | -------------------------------------------------------------------------------- /ch4/4-1.js: -------------------------------------------------------------------------------- 1 | const ChildComponent = React.createClass({ 2 | render: function() { 3 | console.log('ChildComponent: render'); 4 | return ( 5 |
6 | Props: {this.props.name} 7 |
8 | ); 9 | } 10 | }); 11 | 12 | const ParentComponent = React.createClass({ 13 | onInputChange: function(e) { 14 | this.setState({text: e.target.value}); 15 | }, 16 | render: function() { 17 | console.log('ParentComponent: render'); 18 | return ( 19 |
20 |

21 | Learn about rendering and lifecycle methods! 22 |

23 | 24 | 25 |
26 | ); 27 | } 28 | }); 29 | 30 | ReactDOM.render(, document.getElementById('container')); 31 | -------------------------------------------------------------------------------- /ch4/4-10.js: -------------------------------------------------------------------------------- 1 | //… 2 | { this.state.loaded ?
loaded!
:
not loaded
} 3 | //… 4 | -------------------------------------------------------------------------------- /ch4/4-11.js: -------------------------------------------------------------------------------- 1 | // … 2 | render(){ 3 | return ( 4 |
5 | { 6 | this.state.loaded ? 7 | this.state.posts.map(post => { 8 | return ( 9 |
10 | {post.content} 11 |
12 | ); 13 | }) 14 | : 15 |
16 | Loading! 17 |
18 | } 19 |
20 | ); 21 | } 22 | //… 23 | -------------------------------------------------------------------------------- /ch4/4-12.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | 3 | const Post = (props) => { 4 | return ( 5 |
6 |

7 | {post.content} 8 |

9 |
10 | ); 11 | } 12 | 13 | Post.propTypes = { 14 | post: PropTypes.object.isRequired, 15 | } 16 | -------------------------------------------------------------------------------- /ch4/4-13.js: -------------------------------------------------------------------------------- 1 | import Post from ‘./Post’; 2 | // .. 3 | render() { 4 | return ( 5 |
6 | this.state.loaded ? 7 | state.posts.map(post => ) 8 | : 9 |
Loading!
10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /ch4/4-2.js: -------------------------------------------------------------------------------- 1 | const ChildComponent = React.createClass({ 2 | propTypes: { 3 | name: React.PropTypes.string 4 | }, 5 | getInitialState: function() { 6 | console.log('ChildComponent: getInitialState'); 7 | return {name: 'Mark'}; 8 | }, 9 | render: function() { 10 | console.log('ChildComponent: render'); 11 | return ( 12 |
13 | Props: {this.props.name} 14 |
15 | ); 16 | } 17 | }); 18 | 19 | const ParentComponent = React.createClass({ 20 | getDefaultProps: function() { 21 | console.log('ParentComponent: getDefaultProps'); 22 | }, 23 | getInitialState: function() { 24 | console.log('ParentComponent: getInitialState'); 25 | return {text: ''}; 26 | }, 27 | render: function() { 28 | console.log('ParentComponent: render'); 29 | return ( 30 |
31 |

Learn about rendering and lifecycle methods!

32 | 33 | 34 |
35 | ); 36 | } 37 | }); 38 | 39 | ReactDOM.render( 40 | , 41 | document.getElementById('container') 42 | ); 43 | -------------------------------------------------------------------------------- /ch4/4-3.js: -------------------------------------------------------------------------------- 1 | const ParentComponent = React.createClass({ 2 | getDefaultProps: function() { 3 | console.log('ParentComponent: getDefaultProps'); 4 | }, 5 | getInitialState: function() { 6 | console.log('ParentComponent: getInitialState'); 7 | return {text: ''}; 8 | }, 9 | componentWillMount: function() { 10 | console.log('ParentComponent: componentWillMount'); 11 | }, 12 | componentDidMount: function() { 13 | console.log('ParentComponent: componentDidMount'); 14 | }, 15 | componentWillUnmount: function() { 16 | console.log('ParentComponent: componentWillUnmount'); 17 | }, 18 | onInputChange: function(e) { 19 | this.setState({text: e.target.value}); 20 | }, 21 | render: function() { 22 | console.log('ParentComponent: render'); 23 | return ( 24 |
25 |

Let's learn about rendering and lifecycle methods!

26 | 27 | 28 |
29 | ); 30 | } 31 | }); 32 | -------------------------------------------------------------------------------- /ch4/4-4.js: -------------------------------------------------------------------------------- 1 | const ChildComponent = React.createClass({ 2 | //... 3 | shouldComponentUpdate: function(nextProps, nextState) { 4 | console.log(' - shouldComponentUpdate()'); 5 | console.log('nextProps: ', nextProps); 6 | console.log('nextnextState: ', nextState); 7 | return true; 8 | }, 9 | componentWillUpdate: function(nextProps, nextState) { 10 | console.log(' - componentWillUpdate'); 11 | console.log('nextProps: ', nextProps); 12 | console.log('nextState: ', nextState); 13 | }, 14 | componentDidUpdate: function(previousProps, previousState) { 15 | console.log('ChildComponent: componentDidUpdate'); 16 | console.log('previousProps:', previousProps); 17 | console.log('previousState:', previousState); 18 | }, 19 | //... 20 | }); 21 | -------------------------------------------------------------------------------- /ch4/4-5.js: -------------------------------------------------------------------------------- 1 | // ChildComponent : getDefaultProps 2 | // ParentComponent - getDefaultProps 3 | // ParentComponent - getInitialState 4 | // ParentComponent - componentWillMount 5 | // ParentComponent - render 6 | // ChildComponent : componentWillMount 7 | // ChildComponent - render 8 | // ChildComponent : componentDidMount 9 | // ParentComponent - componentDidMount 10 | // ParentComponent - render 11 | // ChildComponent : componentWillReceiveProps() 12 | // Object {text: "Mark"} //A 13 | // - shouldComponentUpdate() 14 | // nextProps: Object {text: "Mark"} 15 | // nextnextState: Object {name: "Mark"} 16 | // - componentWillUpdate 17 | // nextProps: Object {text: "Mark"} 18 | // nextState: Object {name: "Mark"} 19 | // ChildComponent - render 20 | // ChildComponent - componentDidUpdate 21 | // previousProps: Object {text: ""} 22 | // previousState: Object {name: "Mark"} 23 | -------------------------------------------------------------------------------- /ch4/4-6.js: -------------------------------------------------------------------------------- 1 | const ChildComponent = React.createClass({ 2 | //... 3 | componentWillUnmount: function() { 4 | console.log('ChildComponent: componentWillUnmount'); 5 | }, 6 | //... 7 | render: function() { 8 | console.log('ChildComponent: render'); 9 | return ( 10 |
11 | Props: {this.props.name} 12 |
13 | ); 14 | } 15 | }); 16 | 17 | const ParentComponent = React.createClass({ 18 | //... 19 | componentWillUnmount: function() { 20 | console.log('ParentComponent: componentWillUnmount'); 21 | }, 22 | //... 23 | render: function() { 24 | console.log('ParentComponent: render'); 25 | return ( 26 |
27 |

Learn about rendering and lifecycle methods!

28 | 29 | 30 |
31 | ); 32 | } 33 | }); 34 | //... 35 | -------------------------------------------------------------------------------- /ch4/4-7.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export class App extends React.Component { 4 | constructor() { 5 | super(); 6 | this.state = { 7 | posts: { 8 | all: [], 9 | filtered: [] 10 | }, 11 | category: null, 12 | filters: { 13 | image: null, 14 | link: null, 15 | categories: [] 16 | }, 17 | loaded: false, 18 | showBanner: false 19 | }; 20 | } 21 | 22 | render() { 23 | return ( 24 |
25 | Letters Social— coming soon! 26 |
27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ch4/4-8.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { App } from './components/app'; 4 | 5 | render(, document.getElementById('app')); 6 | -------------------------------------------------------------------------------- /ch4/4-9.js: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-fetch'; 2 | 3 | // … 4 | 5 | componentDidMount() { 6 | fetch(‘http://localhost:3500/posts?_limit=25’) 7 | .then(res => res.json()) 8 | .then(posts => { 9 | this.setState({ 10 | posts: { 11 | posts, 12 | }, 13 | loaded: true, 14 | }); 15 | }); 16 | } 17 | //… 18 | -------------------------------------------------------------------------------- /ch5/5-1.js: -------------------------------------------------------------------------------- 1 | // Post schema 2 | class Post { 3 | comments: ?Array; 4 | content: string; 5 | date: Date; 6 | id: string; 7 | image: ?string; 8 | link: ?Object; 9 | user: ?Object; 10 | likes: number; 11 | categories: Array; 12 | } 13 | --------------------------------------------------------------------------------