From 18c2147263eb4f775c0767d6a0bd33be402ba1ab Mon Sep 17 00:00:00 2001 From: Bianca Power Date: Sat, 2 Dec 2017 11:25:02 +1100 Subject: [PATCH 01/17] fix minor typo --- manuscript/chapter1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manuscript/chapter1.md b/manuscript/chapter1.md index 3d5fd20..f4739b9 100644 --- a/manuscript/chapter1.md +++ b/manuscript/chapter1.md @@ -270,7 +270,7 @@ The **element** it returns is specified in the `render()` method. Elements are w Pretty soon, you will see where the App component is instantiated. Otherwise you wouldn't see the rendered output in the browser, would you? The App component is only the declaration, but not the usage. You would instantiate the component somewhere in your JSX with ``. -The content in the render block looks pretty similar to HTML, but it's JSX. JSX allows you to mix HTML and JavaScript. It's powerful yet confusing when you are used to separate your HTML and JavaScript. That's why a good starting point is to use basic HTML in your JSX. In the beginning, remove all the distracting content in the file. +The content in the render block looks pretty similar to HTML, but it's JSX. JSX allows you to mix HTML and JavaScript. It's powerful yet confusing when you are used to separating your HTML and JavaScript. That's why a good starting point is to use basic HTML in your JSX. In the beginning, remove all the distracting content in the file. {title="src/App.js",lang=javascript} ~~~~~~~~ From 9abcae143f7ff92d3a180e284089f8cf0df769b8 Mon Sep 17 00:00:00 2001 From: Bianca Power Date: Sat, 2 Dec 2017 11:31:01 +1100 Subject: [PATCH 02/17] fix minor typo This is an example of an exception to the rule of "an" before words starting with a vowel, because the "u" in "user" makes the same sound as a "y". --- manuscript/chapter1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manuscript/chapter1.md b/manuscript/chapter1.md index 3d5fd20..5a13619 100644 --- a/manuscript/chapter1.md +++ b/manuscript/chapter1.md @@ -322,7 +322,7 @@ Additionally you might have noticed the `className` attribute. It reflects the s ### Exercises: * define more variables and render them in your JSX - * use a complex object to represent an user with a first name and last name + * use a complex object to represent a user with a first name and last name * render the user properties in your JSX * read more about [JSX](https://facebook.github.io/react/docs/introducing-jsx.html) * read more about [React components, elements and instances](https://facebook.github.io/react/blog/2015/12/18/react-components-elements-and-instances.html) From 87c6072a3804b07905321bda4f7130368beb79a0 Mon Sep 17 00:00:00 2001 From: Bianca Power Date: Sat, 2 Dec 2017 11:53:39 +1100 Subject: [PATCH 03/17] Added missing files to folder structure With default settings in current version of create-react-app (1.4.3) these two files are also added. --- manuscript/chapter1.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/manuscript/chapter1.md b/manuscript/chapter1.md index 3d5fd20..5ac4745 100644 --- a/manuscript/chapter1.md +++ b/manuscript/chapter1.md @@ -183,6 +183,7 @@ hackernews/ public/ favicon.ico index.html + manifest.json src/ App.css App.js @@ -190,6 +191,7 @@ hackernews/ index.css index.js logo.svg + registerServiceWorker.js ~~~~~~~~ A short break down of the folder and files. It is fine if you don't understand all of them in the beginning. From c306460d516f3599b382f96034388a1b224446b3 Mon Sep 17 00:00:00 2001 From: Bianca Power Date: Sun, 3 Dec 2017 10:36:29 +1100 Subject: [PATCH 04/17] added clarification for additional files --- manuscript/chapter1.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/manuscript/chapter1.md b/manuscript/chapter1.md index 5ac4745..ad43022 100644 --- a/manuscript/chapter1.md +++ b/manuscript/chapter1.md @@ -206,6 +206,8 @@ A short break down of the folder and files. It is fine if you don't understand a * **public/:** The folder holds all your files when building your project for production. Eventually all your written code in the *src/* folder will be bundled into a couple of files when building your project and placed in the public folder. +* **manifest.json** and **registerServiceWorker.js:** don't worry about what these files do at this stage, we won't be needing them in this project. + After all, you don't need to touch the mentioned files and folders. In the beginning everything you need is located in the *src/* folder. The main focus lies on the *src/App.js* file to implement React components. It will be used to implement your application, but later you might want to split up your components into multiple files whereas each file maintains one or a few components on its own. Additionally, you will find a *src/App.test.js* file for your tests and a *src/index.js* as entry point to the React world. You will get to know both files in a later chapter. In addition, there is a *src/index.css* and a *src/App.css* file to style your general application and your components. They all come with default style when you open them. From e3d3654361d54c2c77e19747a2f522e05bfa9bc7 Mon Sep 17 00:00:00 2001 From: nitin Date: Mon, 11 Dec 2017 23:06:58 +0530 Subject: [PATCH 05/17] exit npm start from command line --- manuscript/chapter1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manuscript/chapter1.md b/manuscript/chapter1.md index c939606..f36179b 100644 --- a/manuscript/chapter1.md +++ b/manuscript/chapter1.md @@ -230,7 +230,7 @@ The scripts are defined in your *package.json*. Your boilerplate React applicati ### Exercises: -* `npm start` your application and visit the application in your browser +* `npm start` your application and visit the application in your browser (you can exit the command by pressing Control + C ) * run the interactive `npm test` script * run the `npm run build` script and verify that a *build/* folder was added to your project (you can remove it again afterward; note that the build folder can be used later on to [deploy your application](https://www.robinwieruch.de/deploy-applications-digital-ocean/)) * make yourself familiar with the folder structure From d3e50f8d7a192415a299dfaf5971f7c3e66111e7 Mon Sep 17 00:00:00 2001 From: Robin Wieruch Date: Tue, 12 Dec 2017 10:01:40 +0800 Subject: [PATCH 06/17] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 39df6aa..47f3e7e 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,5 @@ You can open up any PR that corrects spelling or explains a certain lesson with In addition, you can open Issues when you run into problems. In order to make the fix for the Issue as easy as possible, please provide a couple of details such as error log, screenshot, which page of the book it happened, your node version (command line: node -v) and a link to your own repository. Not all of these details are mandatory, but most of them help to fix the Issue and to improve the book. ---- - -Thanks for your help, +Thanks a lot for your help, Robin From 04ba8797756635cf11860c7ce0a5f58d78f41ebc Mon Sep 17 00:00:00 2001 From: Robin Wieruch Date: Sat, 23 Dec 2017 16:34:24 +0800 Subject: [PATCH 07/17] fix https://github.com/the-road-to-learn-react/the-road-to-learn-react/issues/90 --- manuscript/chapter5.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/manuscript/chapter5.md b/manuscript/chapter5.md index f14093f..7d4424c 100644 --- a/manuscript/chapter5.md +++ b/manuscript/chapter5.md @@ -86,7 +86,9 @@ Now you can focus the input field when the component mounted by using the `this` class Search extends Component { # leanpub-start-insert componentDidMount() { - this.input.focus(); + if(this.input) { + this.input.focus(); + } } # leanpub-end-insert From 8b42c72a7465ac5f98198c25fe49e94199107d21 Mon Sep 17 00:00:00 2001 From: Robin Wieruch Date: Sat, 23 Dec 2017 16:41:14 +0800 Subject: [PATCH 08/17] fix https://github.com/the-road-to-learn-react/the-road-to-learn-react/issues/89 --- manuscript/chapter4.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/manuscript/chapter4.md b/manuscript/chapter4.md index 451146a..4e90a18 100644 --- a/manuscript/chapter4.md +++ b/manuscript/chapter4.md @@ -359,6 +359,8 @@ it('renders without crashing', () => { The "it"-block describes one test case. It comes with a test description and when you test it, it can either succeed or fail. Furthermore, you could wrap it into a "describe"-block that defines your test suit. A test suit could include a bunch of the "it"-blocks for one specific component. You will see those "describe"-blocks later on. Both blocks are used to separated and organize your test cases. +Note that the `it` function is acknowledged in the JavaScript community as the function where you run a single test. However, in Jest it is often found as an alias `test` function. + You can run your test cases by using the interactive *create-react-app* test script on the command line. You will get the output for all test cases on your command line interface. {title="Command Line",lang="text"} From 901cf2f11449a39019672a80df96d2fb1be60bf1 Mon Sep 17 00:00:00 2001 From: Robin Wieruch Date: Sat, 23 Dec 2017 16:58:13 +0800 Subject: [PATCH 09/17] fix https://github.com/the-road-to-learn-react/the-road-to-learn-react/issues/82 --- manuscript/chapter3.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/manuscript/chapter3.md b/manuscript/chapter3.md index 378d075..e4bd27f 100644 --- a/manuscript/chapter3.md +++ b/manuscript/chapter3.md @@ -202,6 +202,8 @@ Let's recap what happens during the component lifecycle. Your component gets ini You used the native fetch API that is supported by most browsers to perform an asynchronous request to an API. The *create-react-app* configuration makes sure that it is supported in every browser. There are third-party node packages that you can use to substitute the native fetch API: [superagent](https://github.com/visionmedia/superagent) and [axios](https://github.com/mzabriskie/axios). +Keep in mind that the book builds up on the JavaScript's shorthand notation for truthfulness checks. In the previous example, `if (!result)` was used in favor of `if (result === null)`. The same applies for other cases throughout the book too. For instance, `if (!list.length)` is used in favor of `if (list.length === 0)` or `if (someString)` is used in favor of `if (someString !== '')`. Read up about the topic if you are not too familiar with it. + Back to your application: The list of hits should be visible now. However, there are two regression bugs in the application now. First, the "Dismiss" button is broken. It doesn't know about the complex result object and still operates on the plain list from the local state when dismissing an item. Second, when the list is displayed but you try to search for something else, the list gets filtered on the client-side even though the initial search was made by searching for stories on the server-side. The perfect behvaior would be to fetch another result object from the API when using the Search component. Both regression bugs will be fixed in the following chapters. ### Exercises: From d867eb0f607390c747829659c37c7b28040824d9 Mon Sep 17 00:00:00 2001 From: Robin Wieruch Date: Wed, 27 Dec 2017 20:43:53 +0100 Subject: [PATCH 10/17] Update README.md --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 47f3e7e..e72cc4e 100644 --- a/README.md +++ b/README.md @@ -18,3 +18,13 @@ In addition, you can open Issues when you run into problems. In order to make th Thanks a lot for your help, Robin + +## Backers + +Support us with a monthly donation and help us continue our activities. +[[Become a backer](https://opencollective.com/the-road-to-learn-react#backer)] + +## Sponsors + +Become a sponsor and get your logo on our README on GitHub with a link to your +site. [[Become a sponsor](https://opencollective.com/the-road-to-learn-react#sponsor)] From 994d3669a5bbcaf7f969f92f41f7709be6efec14 Mon Sep 17 00:00:00 2001 From: Robin Wieruch Date: Wed, 27 Dec 2017 20:44:15 +0100 Subject: [PATCH 11/17] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e72cc4e..9af428e 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,9 @@ Robin ## Backers Support us with a monthly donation and help us continue our activities. -[[Become a backer](https://opencollective.com/the-road-to-learn-react#backer)] +[Become a backer](https://opencollective.com/the-road-to-learn-react#backer) ## Sponsors Become a sponsor and get your logo on our README on GitHub with a link to your -site. [[Become a sponsor](https://opencollective.com/the-road-to-learn-react#sponsor)] +site. [Become a sponsor](https://opencollective.com/the-road-to-learn-react#sponsor) From 36a033c2813645840549905756ebc8ade992fee0 Mon Sep 17 00:00:00 2001 From: Robin Wieruch Date: Fri, 12 Jan 2018 15:03:49 +0100 Subject: [PATCH 12/17] include Firebase learning path --- manuscript/finalwords.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/manuscript/finalwords.md b/manuscript/finalwords.md index 1df0eb2..036b8bd 100644 --- a/manuscript/finalwords.md +++ b/manuscript/finalwords.md @@ -1,6 +1,6 @@ # Outline -That was the last chapter of the book. I hope you enjoyed reading it and that it helped you to get traction in React. If you liked the book, share it as a way to learn React with your friends. It should be used as giveaway. In addition, you could take 5 minutes to write a quick review about it on [Amazon](https://www.amazon.de/dp/B077HJFCQX). +That was the last chapter of the book. I hope you enjoyed reading it and that it helped you to get traction in React. If you liked the book, share it as a way to learn React with your friends. It should be used as giveaway. In addition, you could take 5 minutes to write a quick review about it on [Amazon](https://www.amazon.com/dp/B077HJFCQX?tag=21moves-20). **But where can you go from here after reading this book?** You can either extend the application on your own or give your own React project a shot. Before you dive into another book, course or tutorial, you should create your own hands-on React project. Do it for one week, take it to production by deploying it somewhere, and reach out to me on [Twitter](https://twitter.com/rwieruch) to showcase it. I am curious what you will build after you have read the book and I will gladly share it with my followers. You can also find me on [GitHub](https://github.com/rwieruch) to share your repository. @@ -10,6 +10,8 @@ If you are looking for further extensions for your application, I can recommend * **Sample Projects:** After learning plain React, it is always good to apply the learnings first in your own projects before learning something new. You could write your own tic-tac-toe game or a simple calculator in React. There are plenty of tutorials out there that use only React to build something exciting. Check out mine about building [a paginated and infinite scrolling list](https://www.robinwieruch.de/react-paginated-list/), [showcasing tweets on a Twitter wall](https://www.robinwieruch.de/react-svg-patterns/) or [connecting your React application to Stripe for charging money](https://www.robinwieruch.de/react-express-stripe-payment/). Experiment with these mini applications to get comfortable in React. +* **Connecting to a Database and/or Authentication:** In a growing React application, you may want to persist data eventually. The data should be stored in a database so that it can survive after a browser session and be shared across different users using your application. The simplest way to introduce a database is using Firebase. In [this comprehensive tutorial](https://www.robinwieruch.de/complete-firebase-authentication-react-tutorial/), you will find a step by step guide on how to use Firebase authentication (sign up, sign in, sign out, ...) in React. Beyond that you will use Firebase's realtime database to store user entities. After that, it's up to you to store more data of your application. + * **Code Organization:** On your way reading the book you came across one chapter about code organization. You could apply these changes now, if you haven't done it yet. It will organize your components in structured files and folders (modules). In addition, it helps to understand and learn the principles of code splitting, reusability, maintainability and module API design. * **Testing:** The book only scratched the surface of testing. If you are not familiar with the general topic, you could dive deeper into the concepts of unit testing and integration testing, especially in context of React applications. On an implementation level, I would recommend to stick to Enzyme and Jest in order to refine your approach of testing with unit tests and snapshot tests in React. From 7667e134d05fe12e072233f411585dff0cfa567a Mon Sep 17 00:00:00 2001 From: Brent Guffens Date: Sat, 13 Jan 2018 11:08:18 +0100 Subject: [PATCH 13/17] typo corrections --- manuscript/chapter1.md | 2 +- manuscript/chapter2.md | 4 ++-- manuscript/chapter3.md | 8 ++++---- manuscript/chapter4.md | 8 ++++---- manuscript/chapter5.md | 4 ++-- manuscript/chapter6.md | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/manuscript/chapter1.md b/manuscript/chapter1.md index f36179b..ad6dc26 100644 --- a/manuscript/chapter1.md +++ b/manuscript/chapter1.md @@ -628,7 +628,7 @@ function () { ... } But you have to be aware of its functionalities. One of them is a different behavior with the `this` object. A function expression always defines its own `this` object. Arrow function expressions still have the `this` object of the enclosing context. Don't get confused when using `this` in an arrow function. -There is another valuable fact about arrow functions regarding the parenthesis. You can remove the parenthesis when the function gets only one argument, but have to keep them when it gets multiple arguments. +There is another valuable fact about arrow functions regarding the parentheses. You can remove the parentheses when the function gets only one argument, but have to keep them when it gets multiple arguments. {title="Code Playground",lang="javascript"} ~~~~~~~~ diff --git a/manuscript/chapter2.md b/manuscript/chapter2.md index 47a4aad..d8bf4d1 100644 --- a/manuscript/chapter2.md +++ b/manuscript/chapter2.md @@ -740,7 +740,7 @@ Another performance relevant topic, that is often mentioned, are the implication ## Interactions with Forms and Events -Let's add another interaction for the application to experience forms and events in React. The interaction is a search functionality. The input of the search field should be used to filter your list temporary based on the title property of an item. +Let's add another interaction for the application to experience forms and events in React. The interaction is a search functionality. The input of the search field should be used to temporarily filter your list based on the title property of an item. In the first step, you are going to define a form with an input field in your JSX. @@ -1442,7 +1442,7 @@ Now, whenever there is no `className` property specified when using the Button c By now you have four ES6 class components. But you can do better. Let me introduce functional stateless components as alternative for ES6 class components. Before you will refactor your components, let's introduce the different types of components in React. -* **Functional Stateless Components:** These components are functions which get an input and return an output. The input are the props. The output is a component instance thus plain JSX. So far it is quite similar to an ES6 class component. However, functional stateless components are functions (functional) and they have no local state (stateless). You cannot access or update the state with `this.state` or `this.setState()` because there is no `this` object. Additionally, they have no lifecycle methods. You didn't learn about lifecycle methods yet, but you already used two: `constructor()` and `render()`. Whereas the constructor runs only once in the lifetime of a component, the `render()` class method runs once in the beginning and every time the component updates. Keep in mind that functional stateless component have no lifecycle methods, when you arrive at the lifecycle methods chapter later on. +* **Functional Stateless Components:** These components are functions which get an input and return an output. The input are the props. The output is a component instance thus plain JSX. So far it is quite similar to an ES6 class component. However, functional stateless components are functions (functional) and they have no local state (stateless). You cannot access or update the state with `this.state` or `this.setState()` because there is no `this` object. Additionally, they have no lifecycle methods. You didn't learn about lifecycle methods yet, but you already used two: `constructor()` and `render()`. Whereas the constructor runs only once in the lifetime of a component, the `render()` class method runs once in the beginning and every time the component updates. Keep in mind that functional stateless components have no lifecycle methods, when you arrive at the lifecycle methods chapter later on. * **ES6 Class Components:** You already used this type of component declaration in your four components. In the class definition, they extend from the React component. The `extend` hooks all the lifecycle methods, available in the React component API, to the component. That way you were able to use the `render()` class method. Additionally, you can store and manipulate state in ES6 class components by using `this.state` and `this.setState()`. diff --git a/manuscript/chapter3.md b/manuscript/chapter3.md index e4bd27f..1c90db2 100644 --- a/manuscript/chapter3.md +++ b/manuscript/chapter3.md @@ -45,7 +45,7 @@ After all, you don't need to know all of these lifecycle methods from the beginn * **componentWillMount()** - It is called before the `render()` lifecycle method. That's why it could be used to set internal component state, because it will not trigger a second rendering of the component. Generally it is recommended to use the `constructor()` to set the initial state. -* **render()** - The lifecycle method is mandatory and returns the elements as an output of the component. The method should be pure and therefore shouldn't modify the component state. It gets an input as props and state and returns an element. +* **render()** - This lifecycle method is mandatory and returns the elements as an output of the component. The method should be pure and therefore shouldn't modify the component state. It gets an input as props and state and returns an element. * **componentDidMount()** - It is called only once when the component mounted. That's the perfect time to do an asynchronous request to fetch data from an API. The fetched data would get stored in the internal component state to display it in the `render()` lifecycle method. @@ -341,7 +341,7 @@ Now the "Dismiss" button should work again, because the `onDismiss()` method is ## Conditional Rendering -The conditional rendering is introduced pretty early in React applications. But not in the case of the book, because there wasn't such an use case yet. The conditional rendering happens when you want to make a decision to render either one or another element. Sometimes it means to render an element or nothing. After all, a conditional rendering simplest usage can be expressed by an if-else statement in JSX. +Conditional rendering is introduced pretty early in React applications. But not in the case of the book, because there wasn't such an use case yet. The conditional rendering happens when you want to make a decision to render either one or another element. Sometimes it means to render an element or nothing. After all, a conditional rendering simplest usage can be expressed by an if-else statement in JSX. The `result` object in the internal component state is `null` in the beginning. So far, the App component returned no elements when the `result` hasn't arrived from the API. That's already a conditional rendering, because you return earlier from the `render()` lifecycle method for a certain condition. The App component either renders nothing or its elements. @@ -458,7 +458,7 @@ class App extends Component { } ~~~~~~~~ -Now the Search component has to add an additional button. The button has to explicitly trigger the search request. Otherwise you would fetch data from the Hacker News API every time when your input field changes. But you want to do it explicitly in a on click handler. +Now the Search component has to add an additional button. The button has to explicitly trigger the search request. Otherwise you would fetch data from the Hacker News API every time when your input field changes. But you want to do it explicitly in a `onClick()` handler. As alternative you could debounce (delay) the `onChange()` function and spare the button, but it would add more complexity at this time and maybe wouldn't be the desired effect. Let's keep it simple without a debounce for now. @@ -736,7 +736,7 @@ fetchSearchTopStories(searchTerm, page = 0) { } ~~~~~~~~ -Afterward, the request to the Hacker News API fetches more list items in one request than before. As you can see, a powerful such as the Hacker News API gives you plenty of ways to experiment with real world data. You should make use of it to make your endeavours when learning something new more exciting. That's [how I learned about the empowerment that APIs provide](https://www.robinwieruch.de/what-is-an-api-javascript/) when learning a new programming language or library. +Afterward, the request to the Hacker News API fetches more list items in one request than before. As you can see, a powerful API such as the Hacker News API gives you plenty of ways to experiment with real world data. You should make use of it to make your endeavours when learning something new more exciting. That's [how I learned about the empowerment that APIs provide](https://www.robinwieruch.de/what-is-an-api-javascript/) when learning a new programming language or library. ### Exercises: diff --git a/manuscript/chapter4.md b/manuscript/chapter4.md index 4e90a18..60044b0 100644 --- a/manuscript/chapter4.md +++ b/manuscript/chapter4.md @@ -357,7 +357,7 @@ it('renders without crashing', () => { }); ~~~~~~~~ -The "it"-block describes one test case. It comes with a test description and when you test it, it can either succeed or fail. Furthermore, you could wrap it into a "describe"-block that defines your test suit. A test suit could include a bunch of the "it"-blocks for one specific component. You will see those "describe"-blocks later on. Both blocks are used to separated and organize your test cases. +The "it"-block describes one test case. It comes with a test description and when you test it, it can either succeed or fail. Furthermore, you could wrap it into a "describe"-block that defines your test suite. A test suite could include a bunch of the "it"-blocks for one specific component. You will see those "describe"-blocks later on. Both blocks are used to separated and organize your test cases. Note that the `it` function is acknowledged in the JavaScript community as the function where you run a single test. However, in Jest it is often found as an alias `test` function. @@ -384,7 +384,7 @@ Before writing your first snapshot test with Jest, you have to install an utilit npm install --save-dev react-test-renderer ~~~~~~~~ -Now you can extend the App component test with your first snapshot test. First, import the new functionality from the node package and wrap your previous "it"-block for the App component into a descriptive "describe"-block. In this case, the test suit is only for the App component. +Now you can extend the App component test with your first snapshot test. First, import the new functionality from the node package and wrap your previous "it"-block for the App component into a descriptive "describe"-block. In this case, the test suite is only for the App component. {title="src/App.test.js",lang=javascript} ~~~~~~~~ @@ -700,7 +700,7 @@ Additionally you have two more PropTypes to define a renderable fragment (node), * PropTypes.node * PropTypes.element -You already used the `node` PropType for the Button component. Overall there are more PropType definitions that you can read up in the official React documentation. +You already used the `node` PropType for the Button component. Overall there are more PropType definitions that you can read up on in the official React documentation. At the moment all of the defined PropTypes for the Button are optional. The parameters can be null or undefined. But for several props you want to enforce that they are defined. You can make it a requirement that these props are passed to the component. @@ -729,7 +729,7 @@ Table.propTypes = { # leanpub-end-insert ~~~~~~~~ -You can define the content of an array PropType more explicit: +You can define the content of an array PropType more explicitly: {title="src/App.js",lang=javascript} ~~~~~~~~ diff --git a/manuscript/chapter5.md b/manuscript/chapter5.md index 7d4424c..eb85aaf 100644 --- a/manuscript/chapter5.md +++ b/manuscript/chapter5.md @@ -8,7 +8,7 @@ Sometimes you need to interact with your DOM nodes in React. The `ref` attribute * to use the DOM API (focus, media playback etc.) * to invoke imperative DOM node animations -* to integrate with third-party library that needs the DOM node (e.g. [D3.js](https://d3js.org/)) +* to integrate with a third-party library that needs the DOM node (e.g. [D3.js](https://d3js.org/)) Let's do it by example with the Search component. When the application renders the first time, the input field should be focused. That's one use case where you would need access to the DOM API. This chapter will show you how it works, but since it is not very useful for the application itself, we will omit the changes after the chapter. You can keep it for your own application though. @@ -420,7 +420,7 @@ You can either fix the component now, when you think there is something wrong ab Higher order components are an advanced technique in React. They have multiple purposes like improved reusability of components, greater abstraction, composability of components and manipulations of props, state and view. Don't worry if you don't understand them immediately. It takes time to get used to them. -I encourage you to read the [gentle introduction to higher order components](https://www.robinwieruch.de/gentle-introduction-higher-order-components/). It gives you another approach to learn them, shows you an elegant way to use them a functional programming way and solves specifically the problem of conditional rendering with higher order components. +I encourage you to read the [gentle introduction to higher order components](https://www.robinwieruch.de/gentle-introduction-higher-order-components/). It gives you another approach to learn them, shows you an elegant way to use them in a functional programming way and solves specifically the problem of conditional rendering with higher order components. ### Exercises: diff --git a/manuscript/chapter6.md b/manuscript/chapter6.md index 8a38f07..4493871 100644 --- a/manuscript/chapter6.md +++ b/manuscript/chapter6.md @@ -8,7 +8,7 @@ Only the App component is a stateful ES6 component in your application. It handl The whole sort functionality is only used in the Table component. You could move it into the Table component, because the App component doesn't need to know about it at all. The process of refactoring substate from one component to another is known as *lifting state*. In your case, you want to move state that isn't used in the App component into the Table component. The state moves down from parent to child component. -In order to deal with state and class methods in the Table component, it has to become an ES6 class component. The refactoring from functional stateless component to ES6 class component is straight forward. +In order to deal with state and class methods in the Table component, it has to become an ES6 class component. The refactoring from functional stateless component to ES6 class component is straightforward. Your Table component as a functional stateless component: @@ -445,7 +445,7 @@ That's it. The function over an object approach in `setState()` fixes potential The previous chapters have shown you that state management can be a crucial topic in larger applications. In general, not only React but a lot of SPA frameworks struggle with it. Applications got more complex in the recent years. One big challenge in web applications nowadays is to tame and control the state. -Compared to other solutions, React already made a big step forward. The unidirectional data flow and a simple API to manage state in a component are indispensable. These concepts make it easier to reason about your state and your state changes. It makes it easier to reason about it on a component level and to a certain degree on a application level. +Compared to other solutions, React already made a big step forward. The unidirectional data flow and a simple API to manage state in a component are indispensable. These concepts make it easier to reason about your state and your state changes. It makes it easier to reason about it on a component level and to a certain degree on an application level. In a growing application, it gets harder to reason about state changes. You can introduce bugs by operating on stale state when using an object over a function in `setState()`. You have to lift state around to share necessary or hide unnecessary state across components. It can happen that a component needs to lift up state, because its sibling component depends on it. Perhaps the component is far away in the component tree and thus you have to share the state across the whole component tree. In conclusion components get involved to a greater extent in state management. But after all, the main responsibility of components should be representing the UI, shouldn't it? From 98c6617e148e8288fa99110ada3ba10aaf6d4495 Mon Sep 17 00:00:00 2001 From: Brent Guffens Date: Sat, 13 Jan 2018 11:17:32 +0100 Subject: [PATCH 14/17] typo correction 2 --- manuscript/chapter2.md | 16 ++++++++-------- manuscript/chapter5.md | 12 ++++++------ manuscript/chapter6.md | 4 ++-- manuscript/foreword.md | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/manuscript/chapter2.md b/manuscript/chapter2.md index d8bf4d1..1158840 100644 --- a/manuscript/chapter2.md +++ b/manuscript/chapter2.md @@ -571,7 +571,7 @@ That's already a complex use case, because you have to pass a value to the class When using `onClick={doSomething()}`, the `doSomething()` function would execute immediately when you open the application in your browser. The expression in the handler is evaluated. Since the returned value of the function isn't a function anymore, nothing would happen when you click the button. But when using `onClick={doSomething}` whereas `doSomething` is a function, it would be executed when clicking the button. The same rules apply for the `onDismiss()` class method that is used in your application. -However, using `onClick={this.onDismiss}` wouldn't suffice, because somehow the `item.objectID` property needs to be passed to the class method to identify the item that is going to be dismissed. That's why it can be wrapped into another function to sneak in the property. The concept is called higher order functions in JavaScript and will be explained briefly later on. +However, using `onClick={this.onDismiss}` wouldn't suffice, because somehow the `item.objectID` property needs to be passed to the class method to identify the item that is going to be dismissed. That's why it can be wrapped into another function to sneak in the property. The concept is called higher-order functions in JavaScript and will be explained briefly later on. {title="src/App.js",lang=javascript} ~~~~~~~~ @@ -732,7 +732,7 @@ class App extends Component { } ~~~~~~~~ -Another performance relevant topic, that is often mentioned, are the implications of using arrow functions in event handlers. For instance, the `onClick` handler for the `onDismiss()` method is wrapping the method in another arrow function to be able to pass the item identifier. So every time the `render()` method runs, the handler instantiates the higher order arrow function. It *can* have an impact on your application performance, but in most cases you will not notice it. Imagine you have a huge table of data with 1000 items and each row or column has such an arrow function in an event handler. Then it is worth to think about the performance implications and therefore you could implement a dedicated Button component to bind the method in the constructor. But before that happens it is premature optimization. It is more valuable to focus on learning React itself. +Another performance relevant topic, that is often mentioned, are the implications of using arrow functions in event handlers. For instance, the `onClick` handler for the `onDismiss()` method is wrapping the method in another arrow function to be able to pass the item identifier. So every time the `render()` method runs, the handler instantiates the higher-order arrow function. It *can* have an impact on your application performance, but in most cases you will not notice it. Imagine you have a huge table of data with 1000 items and each row or column has such an arrow function in an event handler. Then it is worth to think about the performance implications and therefore you could implement a dedicated Button component to bind the method in the constructor. But before that happens it is premature optimization. It is more valuable to focus on learning React itself. ### Exercises: @@ -916,11 +916,11 @@ class App extends Component { } ~~~~~~~~ -Let's approach the filter function in a different way this time. We want to define the filter argument, the function that is passed to the filter function, outside of the ES6 class component. There we don't have access to the state of the component and thus we have no access to the `searchTerm` property to evaluate the filter condition. We have to pass the `searchTerm` to the filter function and have to return a new function to evaluate the condition. That's called a higher order function. +Let's approach the filter function in a different way this time. We want to define the filter argument, the function that is passed to the filter function, outside of the ES6 class component. There we don't have access to the state of the component and thus we have no access to the `searchTerm` property to evaluate the filter condition. We have to pass the `searchTerm` to the filter function and have to return a new function to evaluate the condition. That's called a higher-order function. -Normally I wouldn't mention higher order functions, but in a React book it makes total sense. It makes sense to know about higher order functions, because React deals with a concept called higher order components. You will get to know the concept later in the book. Now again, let's focus on the filter functionality. +Normally I wouldn't mention higher-order functions, but in a React book it makes total sense. It makes sense to know about higher-order functions, because React deals with a concept called higher-order components. You will get to know the concept later in the book. Now again, let's focus on the filter functionality. -First, you have to define the higher order function outside of your App component. +First, you have to define the higher-order function outside of your App component. {title="src/App.js",lang=javascript} ~~~~~~~~ @@ -987,7 +987,7 @@ const isSearched = searchTerm => item => item.title.toLowerCase().includes(searchTerm.toLowerCase()); ~~~~~~~~ -One could argue which function is more readable. Personally I prefer the second one. The React ecosystem uses a lot of functional programming concepts. It happens often that you will use a function which returns a function (higher order functions). In JavaScript ES6, you can express these more concisely with arrow functions. +One could argue which function is more readable. Personally I prefer the second one. The React ecosystem uses a lot of functional programming concepts. It happens often that you will use a function which returns a function (higher-order functions). In JavaScript ES6, you can express these more concisely with arrow functions. Last but not least, you have to use the defined `isSearched()` function to filter your list. You pass it the `searchTerm` property from your local state, it returns the filter input function, and filters your list based on the filter condition. Afterward it maps over the filtered list to display an element for each list item. @@ -1022,7 +1022,7 @@ The search functionality should work now. Try it yourself in the browser. ### Exercises: * read more about [React events](https://facebook.github.io/react/docs/handling-events.html) -* read more about [higher order functions](https://en.wikipedia.org/wiki/Higher-order_function) +* read more about [higher-order functions](https://en.wikipedia.org/wiki/Higher-order_function) ## ES6 Destructuring @@ -1814,7 +1814,7 @@ You have learned the basics to write your own React application! Let's recap the * destructuring of objects and arrays * default parameters * General - * higher order functions + * higher-order functions Again it makes sense to take a break. Internalize the learnings and apply them on your own. You can experiment with the source code you have written so far. Additionally you can read more in the official [documentation](https://facebook.github.io/react/docs/installation.html). diff --git a/manuscript/chapter5.md b/manuscript/chapter5.md index eb85aaf..23c9160 100644 --- a/manuscript/chapter5.md +++ b/manuscript/chapter5.md @@ -1,6 +1,6 @@ # Advanced React Components -The chapter will focus on the implementation of advanced React components. You will learn about higher order components and how to implement them. In addition you will dive into more advanced topics in React and implement complex interactions with it. +The chapter will focus on the implementation of advanced React components. You will learn about higher-order components and how to implement them. In addition you will dive into more advanced topics in React and implement complex interactions with it. ## Ref a DOM Element @@ -281,9 +281,9 @@ Initially the Loading component will show up when you start your application, be * use a library such as [Font Awesome](http://fontawesome.io/) to show a loading icon instead of the "Loading ..." text -## Higher Order Components +## Higher-Order Components -Higher order components (HOC) are an advanced concept in React. HOCs are an equivalent to higher order functions. They take any input - most of the time a component, but also optional arguments - and return a component as output. The returned component is an enhanced version of the input component and can be used in your JSX. +Higher order components (HOC) are an advanced concept in React. HOCs are an equivalent to higher-order functions. They take any input - most of the time a component, but also optional arguments - and return a component as output. The returned component is an enhanced version of the input component and can be used in your JSX. HOCs are used for different use cases. They can prepare properties, manage state or alter the representation of a component. One use case could be to use a HOC as a helper for a conditional rendering. Imagine you have a List component that renders a list of items or nothing, because the list is empty or null. The HOC could shield away that the list would render nothing when there is no list. On the other hand, the plain List component doesn't need to bother anymore about an non existent list. It only cares about rendering the list. @@ -420,11 +420,11 @@ You can either fix the component now, when you think there is something wrong ab Higher order components are an advanced technique in React. They have multiple purposes like improved reusability of components, greater abstraction, composability of components and manipulations of props, state and view. Don't worry if you don't understand them immediately. It takes time to get used to them. -I encourage you to read the [gentle introduction to higher order components](https://www.robinwieruch.de/gentle-introduction-higher-order-components/). It gives you another approach to learn them, shows you an elegant way to use them in a functional programming way and solves specifically the problem of conditional rendering with higher order components. +I encourage you to read the [gentle introduction to higher-order components](https://www.robinwieruch.de/gentle-introduction-higher-order-components/). It gives you another approach to learn them, shows you an elegant way to use them in a functional programming way and solves specifically the problem of conditional rendering with higher-order components. ### Exercises: -* read [a gentle introduction to higher order components](https://www.robinwieruch.de/gentle-introduction-higher-order-components/) +* read [a gentle introduction to higher-order components](https://www.robinwieruch.de/gentle-introduction-higher-order-components/) * experiment with the HOC you have created * think about a use case where another HOC would make sense * implement the HOC, if there is a use case @@ -978,7 +978,7 @@ You have learned advanced component techniques in React! Let's recap the last ch * React * the ref attribute to reference DOM nodes - * higher order components are a common way to build advanced components + * higher-order components are a common way to build advanced components * implementation of advanced interactions in React * conditional classNames with a neat helper library * ES6 diff --git a/manuscript/chapter6.md b/manuscript/chapter6.md index 4493871..3d48974 100644 --- a/manuscript/chapter6.md +++ b/manuscript/chapter6.md @@ -390,7 +390,7 @@ setSearchTopStories(result) { } ~~~~~~~~ -That will fix the issue with a stale state. There is one more improvement. Since it is a function, you can extract the function for an improved readability. That's one more advantage to use a function over an object. The function can live outside of the component. But you have to use a higher order function to pass the result to it. After all, you want to update the state based on the fetched result from the API. +That will fix the issue with a stale state. There is one more improvement. Since it is a function, you can extract the function for an improved readability. That's one more advantage to use a function over an object. The function can live outside of the component. But you have to use a higher-order function to pass the result to it. After all, you want to update the state based on the fetched result from the API. {title="src/App.js",lang=javascript} ~~~~~~~~ @@ -400,7 +400,7 @@ setSearchTopStories(result) { } ~~~~~~~~ -The `updateSearchTopStoriesState()` function has to return a function. It is a higher order function. You can define this higher order function outside of your App component. Note how the function signature changes slightly now. +The `updateSearchTopStoriesState()` function has to return a function. It is a higher-order function. You can define this higher-order function outside of your App component. Note how the function signature changes slightly now. {title="src/App.js",lang=javascript} ~~~~~~~~ diff --git a/manuscript/foreword.md b/manuscript/foreword.md index 493bb73..81c5912 100644 --- a/manuscript/foreword.md +++ b/manuscript/foreword.md @@ -136,7 +136,7 @@ Since you are reading the book, I guess you are new to React. That's perfect. In * client-sided filtering * server-sided searching * implementation of client-side caching -* higher order functions and higher order components +* higher-order functions and higher-order components * snapshot test components with Jest * unit test components with Enzyme * neat libraries along the way From c9c998d5b22e04be6c5b1f7d37d135c415d60f8d Mon Sep 17 00:00:00 2001 From: Brent Guffens Date: Sat, 13 Jan 2018 11:55:05 +0100 Subject: [PATCH 15/17] typo corrections 3 --- manuscript/chapter5.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manuscript/chapter5.md b/manuscript/chapter5.md index 23c9160..4acd438 100644 --- a/manuscript/chapter5.md +++ b/manuscript/chapter5.md @@ -283,7 +283,7 @@ Initially the Loading component will show up when you start your application, be ## Higher-Order Components -Higher order components (HOC) are an advanced concept in React. HOCs are an equivalent to higher-order functions. They take any input - most of the time a component, but also optional arguments - and return a component as output. The returned component is an enhanced version of the input component and can be used in your JSX. +Higher-order components (HOC) are an advanced concept in React. HOCs are an equivalent to higher-order functions. They take any input - most of the time a component, but also optional arguments - and return a component as output. The returned component is an enhanced version of the input component and can be used in your JSX. HOCs are used for different use cases. They can prepare properties, manage state or alter the representation of a component. One use case could be to use a HOC as a helper for a conditional rendering. Imagine you have a List component that renders a list of items or nothing, because the list is empty or null. The HOC could shield away that the list would render nothing when there is no list. On the other hand, the plain List component doesn't need to bother anymore about an non existent list. It only cares about rendering the list. @@ -418,7 +418,7 @@ When you run your tests again, you will notice that your snapshot test for the A You can either fix the component now, when you think there is something wrong about it, or can accept the new snapshot of it. Because you introduced the Loading component in this chapter, you can accept the altered snapshot test on the command line in the interactive test. -Higher order components are an advanced technique in React. They have multiple purposes like improved reusability of components, greater abstraction, composability of components and manipulations of props, state and view. Don't worry if you don't understand them immediately. It takes time to get used to them. +Higher-order components are an advanced technique in React. They have multiple purposes like improved reusability of components, greater abstraction, composability of components and manipulations of props, state and view. Don't worry if you don't understand them immediately. It takes time to get used to them. I encourage you to read the [gentle introduction to higher-order components](https://www.robinwieruch.de/gentle-introduction-higher-order-components/). It gives you another approach to learn them, shows you an elegant way to use them in a functional programming way and solves specifically the problem of conditional rendering with higher-order components. From 0ec6afb86eb8fe9655241e45fdb6e73b71673426 Mon Sep 17 00:00:00 2001 From: Robin Wieruch Date: Sun, 14 Jan 2018 12:02:17 +0100 Subject: [PATCH 16/17] Update README.md --- README.md | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 9af428e..dd71ecc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # The Road to learn React -The official repository for [The Road to learn React](https://www.robinwieruch.de/the-road-to-learn-react/). In addition, here you can find the [Source Code](https://github.com/the-road-to-learn-react/hackernews-client) and [Complete Course](https://roadtoreact.com/). +The official repository for [The Road to learn React](https://www.robinwieruch.de/the-road-to-learn-react/). In addition, here you can find the [Source Code](https://github.com/the-road-to-learn-react/hackernews-client) and [Complete Course](https://roadtoreact.com/). If you want to leave a review, you can do it on [Amazon](https://www.amazon.com/dp/B077HJFCQX) or [Goodreads](https://www.goodreads.com/book/show/37503118-the-road-to-learn-react). ## Updates, Help and Support @@ -16,15 +16,8 @@ You can open up any PR that corrects spelling or explains a certain lesson with In addition, you can open Issues when you run into problems. In order to make the fix for the Issue as easy as possible, please provide a couple of details such as error log, screenshot, which page of the book it happened, your node version (command line: node -v) and a link to your own repository. Not all of these details are mandatory, but most of them help to fix the Issue and to improve the book. -Thanks a lot for your help, -Robin +Thanks a lot for your help! -## Backers +## Become a Patron -Support us with a monthly donation and help us continue our activities. -[Become a backer](https://opencollective.com/the-road-to-learn-react#backer) - -## Sponsors - -Become a sponsor and get your logo on our README on GitHub with a link to your -site. [Become a sponsor](https://opencollective.com/the-road-to-learn-react#sponsor) +The Road to learn React is a free ebook which should enable everyone to learn about React. This kind of educational content needs your support to sustain itself. Robin Wieruch writes a lot of this educational content on [his website](https://www.robinwieruch.de/) too. So you can support him be being his [Patron on Patreon](https://www.patreon.com/rwieruch). From 7dbf4c35d83e546b3f3e9eb6c088eecf9c94e8c0 Mon Sep 17 00:00:00 2001 From: Robin Wieruch Date: Tue, 16 Jan 2018 19:33:29 +0100 Subject: [PATCH 17/17] add contributors --- manuscript/contributor.md | 7 +++++++ manuscript/helper.md | 41 --------------------------------------- 2 files changed, 7 insertions(+), 41 deletions(-) create mode 100644 manuscript/contributor.md delete mode 100644 manuscript/helper.md diff --git a/manuscript/contributor.md b/manuscript/contributor.md new file mode 100644 index 0000000..5710c4b --- /dev/null +++ b/manuscript/contributor.md @@ -0,0 +1,7 @@ +# Contributor(s) + +Many people made it possible to write and improve *The Road to learn React* over the recent time. Currently, it is one of the most downloaded React.js books out there. Originally the book was written by the german software engineer [Robin Wieruch](https://www.robinwieruch.de/). But all the translations of the book wouldn't be possible without the help of others. This version of the book got translated by ... [tell your personal story here]. + +[Note: Translate and complete this paragraph for your own personal pitch. Include your social media account, GitHub account, website or anything else that is personally related to you. It's your opportunity to tell something about your own work as software engineer or translator. Afterward, include it in the Book.txt below the foreword.md that it can be used to compile the finished ebook.] + +{pagebreak} \ No newline at end of file diff --git a/manuscript/helper.md b/manuscript/helper.md deleted file mode 100644 index 37ee63b..0000000 --- a/manuscript/helper.md +++ /dev/null @@ -1,41 +0,0 @@ -*src/App.js* - -{lang=javascript,style=monokai,hl_lines="1 3"} - -{lang=javascript} -~~~~~~~~ -import React, { Component } from 'react'; -import logo from './logo.svg'; -import './App.css'; - -# leanpub-start-insert -class App extends Component { - render() { -# leanpub-end-insert - const helloWorld = 'Welcome to React'; - return ( -
-
- logo -

{helloWorld}

-
-

- To get started, edit src/App.js and save to reload. -

-
- ); - } -} - -export default App; -~~~~~~~~ - -headers: -# -## - -divider to {pagebreak} - -{pagebreak} after each header - -a_blank \ No newline at end of file