From e8787e5ea3c5c64db937c24e0778863b9cf636ef Mon Sep 17 00:00:00 2001 From: dphaener Date: Wed, 2 Dec 2015 17:32:09 -0800 Subject: [PATCH 01/34] First iteration on Lesson 1.1 --- readme.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 1f558a3..bb7a5fe 100644 --- a/readme.md +++ b/readme.md @@ -1 +1,32 @@ -#ReactJS-the-ES6-Way \ No newline at end of file +# -ReactJS the ES6 Way + +Welcome to ReactJS, the ES6 way! My name is Darin Haener, and I'll be taking +you on a whirlwind introductory tour of ReactJS, and as the course name +suggests, we'll be doing it the ES6 way! + +React is a unique JavaScript framework in that it is *only* the "V" in MVC. +Meaning that it is only used on the "View" layer in web applications. This +allows it to be narrowly focused on doing one thing and doing it well. + +React uses many innovative technologies to create a fast, modular, and +easy to use framework. + +## The Virtual DOM + +This is one term you'll hear thrown around a lot in the React community, +and it is what React uses to make page updates blazing fast and efficient. +We'll be discussing this in more detail later. + +## ES6 + +Hopefully, if you're taking this course, you've made yourself at least a little +bit familiar with the newest JavaScript specification call ECMAScript 2015, +or ES6 for short. We'll be using ES6 to create our React components in this +class, because it's awesome, and makes programming in JavaScript even more +fun. + +Because it's not fully supported in browsers just yet, we'll have to use +[Babel](https://babeljs.io/) to transpile our code down to browser friendly +ES5. + +Buckle up and get ready for some React and ES6 awesomeness! From ccdaf743147c173125aa8f7fdd2d3b5cc7131a5d Mon Sep 17 00:00:00 2001 From: dphaener Date: Wed, 2 Dec 2015 18:01:01 -0800 Subject: [PATCH 02/34] Initial commit for Lesson 1.2 --- readme.md | 64 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/readme.md b/readme.md index bb7a5fe..610b952 100644 --- a/readme.md +++ b/readme.md @@ -1,32 +1,50 @@ -# -ReactJS the ES6 Way +# The Tools of the Trade -Welcome to ReactJS, the ES6 way! My name is Darin Haener, and I'll be taking -you on a whirlwind introductory tour of ReactJS, and as the course name -suggests, we'll be doing it the ES6 way! +## Text Editor -React is a unique JavaScript framework in that it is *only* the "V" in MVC. -Meaning that it is only used on the "View" layer in web applications. This -allows it to be narrowly focused on doing one thing and doing it well. +The very first thing you'll need is a text editor. Hopefully, you've already +got a favorite that you are using already. These days, I prefer Vim, but to +each his/her own. Here are some popular choices: -React uses many innovative technologies to create a fast, modular, and -easy to use framework. + * [Sublime Text](http://www.sublimetext.com/) + * [Atom](https://atom.io/) -## The Virtual DOM +If you prefer a full blown IDE, [WebStorm](https://www.jetbrains.com/webstorm/) +is a good choice, though it will cost you some money. -This is one term you'll hear thrown around a lot in the React community, -and it is what React uses to make page updates blazing fast and efficient. -We'll be discussing this in more detail later. +## Browser -## ES6 +You can use whatever web browser you choose, but I highly recommend using +the latest version of Google Chrome. Google Chrome has a great set of developer +tools for React, and we will be using them throughout the course to help us +debug and gain some insight as to what is happening in the browser when React +renders the components in the DOM. -Hopefully, if you're taking this course, you've made yourself at least a little -bit familiar with the newest JavaScript specification call ECMAScript 2015, -or ES6 for short. We'll be using ES6 to create our React components in this -class, because it's awesome, and makes programming in JavaScript even more -fun. +## GitHub -Because it's not fully supported in browsers just yet, we'll have to use -[Babel](https://babeljs.io/) to transpile our code down to browser friendly -ES5. +We will be using [GitHub](https://github.com/) to store our code, so if you're +not familiar with it, you can find a great general overview of it +[here](https://guides.github.com/activities/hello-world/). I'll be using the +command line in the tutorials, but if that's not your thing, then no sweat, +go ahead and use whatever GUI implementation you'd like. Some popular ones are: + + * [SourceTree](https://www.sourcetreeapp.com/) + * [GitHub Desktop](https://desktop.github.com/) + +## The *Dreaded* Command Line + +Yes, we will be doing some work on the command line. But don't worry, you +don't have to be a Linux SysAdmin to get by here. We'll be using just a few +very simple commands to get our code transpiled, and to start our Node +servers. If you're using OS X or Linux, congratulations, you already have +a great bash terminal installed on your system. If you're using Windows, +you can certainly use the run of the mill MS-DOS prompt, but it can pose +problems installing and running some of our command line tools. I highly +recommend using one of the following: + + * [Cygwin](https://www.cygwin.com/) + * [GitBash](https://git-for-windows.github.io/) + +That's all the tools that we'll need to get started! So let's move on to +the next section and figure out what this NPM thing is... -Buckle up and get ready for some React and ES6 awesomeness! From fd20dd0253292f9fed16c62452608dd3e69c9cbb Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 08:43:15 -0800 Subject: [PATCH 03/34] Update Git section --- readme.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/readme.md b/readme.md index 610b952..06e51f4 100644 --- a/readme.md +++ b/readme.md @@ -23,7 +23,7 @@ renders the components in the DOM. ## GitHub We will be using [GitHub](https://github.com/) to store our code, so if you're -not familiar with it, you can find a great general overview of it +not familiar with it, you can find a great general overview of it [here](https://guides.github.com/activities/hello-world/). I'll be using the command line in the tutorials, but if that's not your thing, then no sweat, go ahead and use whatever GUI implementation you'd like. Some popular ones are: @@ -31,6 +31,13 @@ go ahead and use whatever GUI implementation you'd like. Some popular ones are: * [SourceTree](https://www.sourcetreeapp.com/) * [GitHub Desktop](https://desktop.github.com/) +You'll also need to ensure that Git is installed on your system. If you are +running OS X or Linux, then you've already got it so don't sweat it. If you're +on Windows there is a great solution out there called [Git for Windows](https://git-for-windows.github.io/). +After installation you'll have Git installed, as well as a GUI Git client, +*and* a handy terminal called GitBash that will give you a \*nix like +bash terminal. + ## The *Dreaded* Command Line Yes, we will be doing some work on the command line. But don't worry, you @@ -38,13 +45,10 @@ don't have to be a Linux SysAdmin to get by here. We'll be using just a few very simple commands to get our code transpiled, and to start our Node servers. If you're using OS X or Linux, congratulations, you already have a great bash terminal installed on your system. If you're using Windows, -you can certainly use the run of the mill MS-DOS prompt, but it can pose -problems installing and running some of our command line tools. I highly -recommend using one of the following: +you can certainly use the run of the mill MS-DOS prompt, or you can use +GitBash, which will be installed if you used the link from above. - * [Cygwin](https://www.cygwin.com/) - * [GitBash](https://git-for-windows.github.io/) -That's all the tools that we'll need to get started! So let's move on to +That's all the tools that we'll need to get started! So let's move on to the next section and figure out what this NPM thing is... From c91c36e295e634d09b449177c26747bc667e60a1 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 08:49:37 -0800 Subject: [PATCH 04/34] Add header to end of lesson --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 06e51f4..58bcdbb 100644 --- a/readme.md +++ b/readme.md @@ -48,6 +48,7 @@ a great bash terminal installed on your system. If you're using Windows, you can certainly use the run of the mill MS-DOS prompt, or you can use GitBash, which will be installed if you used the link from above. +## Next lesson... That's all the tools that we'll need to get started! So let's move on to the next section and figure out what this NPM thing is... From f9ad5434d672ec63f2e129a9b4f75f1660b96a7d Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 09:38:48 -0800 Subject: [PATCH 05/34] Lesson 1.3 initial content --- readme.md | 138 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 98 insertions(+), 40 deletions(-) diff --git a/readme.md b/readme.md index 58bcdbb..28212f8 100644 --- a/readme.md +++ b/readme.md @@ -1,55 +1,113 @@ -# The Tools of the Trade +# What's this npm thing anyways? -## Text Editor +npm, commonly referred to as "node package manager" is just that. It's a package +manager for node. Although, npm does *not* stand for "node package manager". +I won't go into the details of that, but if you'd like to, you can read all +about it [here](https://docs.npmjs.com/misc/faq#if-npm-is-an-acronym-why-is-it-never-capitalized). -The very first thing you'll need is a text editor. Hopefully, you've already -got a favorite that you are using already. These days, I prefer Vim, but to -each his/her own. Here are some popular choices: +npm makes it really easy to install, and maintain specific versions of +JavaScript packages without the old copy and paste that we used to have to do +back in the "old days". - * [Sublime Text](http://www.sublimetext.com/) - * [Atom](https://atom.io/) +Application requirements are defined in a file that typically lives in the +root directory of your application called package.json: -If you prefer a full blown IDE, [WebStorm](https://www.jetbrains.com/webstorm/) -is a good choice, though it will cost you some money. +```json +{ + "name": "My Cool App", + "version": "1.0.0", + "description": "The most awesome nebulous app ever made", + "author": "Tony Stark (https://github.com/i-am-fictitious)", + "license": "ISC", + "devDependencies": { + "react-hot-loader": "1.3.0", + "webpack": "1.12.6", + "webpack-dev-server": "1.12.1" + }, + "dependencies": { + "babel-cli": "6.2.0", + "babel-core": "6.1.21", + "babel-loader": "6.2.0", + "babel-polyfill": "^6.2.0", + "babel-preset-es2015": "6.1.18", + "babel-preset-react": "6.1.18", + "babel-preset-stage-0": "6.1.18", + "babel-runtime": "6.1.18", + "css-loader": "^0.23.0", + "express": "4.13.3", + "extract-text-webpack-plugin": "^0.9.1", + "history": "~1.13.1", + "node-sass": "^3.4.2", + "normalize.css": "^3.0.3", + "react": ">=0.14.2", + "react-dom": ">=0.14.2", + "sass-loader": "^3.1.2", + "style-loader": "^0.13.0" + } +} +``` -## Browser +As you can see, the `package.json` files not only specifically says what +JavaScript modules we need to run our application in the `dependencies` +section, but it also includes the modules that aren't needed at run-time, +but we need in order to develop our application, in the `devDependencies` +section. It also includes some ancillary information that is needed if we +are going to push our package up to npm. -You can use whatever web browser you choose, but I highly recommend using -the latest version of Google Chrome. Google Chrome has a great set of developer -tools for React, and we will be using them throughout the course to help us -debug and gain some insight as to what is happening in the browser when React -renders the components in the DOM. +Let's now dive into what some of the weird characters and squiggly lines +that you see in front of some of the version numbers mean. -## GitHub +We'll start with the more obvious `>=`. It simply means "install the newest +version of this package that has at least this version number". Nothing too +ground breaking there, but what about this squiggly line business? -We will be using [GitHub](https://github.com/) to store our code, so if you're -not familiar with it, you can find a great general overview of it -[here](https://guides.github.com/activities/hello-world/). I'll be using the -command line in the tutorials, but if that's not your thing, then no sweat, -go ahead and use whatever GUI implementation you'd like. Some popular ones are: +Let's take a look at the `history` entry in our `package.json` file: +```json +"history": "~1.13.1" +``` +This is called [tilde ranges](https://docs.npmjs.com/misc/semver#tilde-ranges-1-2-3-1-2-1), +and means that it allows the version number to change based on whether or not +the patch or minor version number is specified. In our current setup, any +version greater than or equal to `1.13.1` or less than `1.14.0` will be +an acceptable package. Now, had we specified it this way: +```json +"history": "~1.13" +``` +then the rules change. In this scenario, npm will accept anything that is +greater than or equal to `1.13.0` and less than `1.14.0`. Again, if we remove +one more level of versioning in our dependency: +```json +"history": "~1" +``` +the rules change yet again. Here, npm will accept any version that is greater +than or equal to `1.0` and less than or equal to `2.0`. - * [SourceTree](https://www.sourcetreeapp.com/) - * [GitHub Desktop](https://desktop.github.com/) +Next we'll take a quick peek at the [caret ranges](https://docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4) +that are seen in our `package.json` file: +```json +"sass-loader": "^3.1.2" +``` +From npm: +> Allows changes that do not modify the left-most non-zero digit in +> the [major, minor, patch] tuple. In other words, this allows patch and minor +> updates for versions 1.0.0 and above, patch updates for versions 0.X >=0.1.0, +> and no updates for versions 0.0.X. -You'll also need to ensure that Git is installed on your system. If you are -running OS X or Linux, then you've already got it so don't sweat it. If you're -on Windows there is a great solution out there called [Git for Windows](https://git-for-windows.github.io/). -After installation you'll have Git installed, as well as a GUI Git client, -*and* a handy terminal called GitBash that will give you a \*nix like -bash terminal. +Essentially, this means "give me the newest version of this package that +doesn't have a breaking change". Typically when a package author using +[semver](https://docs.npmjs.com/misc/semver) makes a relatively minor, but +breaking change to their module, they will bump the minor version. So a +`0.1.x` package will become `0.2.0`. Let's say that we had a package that was +at version `0.1.3` and we were using caret ranges. During installation npm +finds two newer version of this package: `0.1.4` and `0.2.0`. Because we specified +a carat range, npm will select the `0.1.4` version. -## The *Dreaded* Command Line -Yes, we will be doing some work on the command line. But don't worry, you -don't have to be a Linux SysAdmin to get by here. We'll be using just a few -very simple commands to get our code transpiled, and to start our Node -servers. If you're using OS X or Linux, congratulations, you already have -a great bash terminal installed on your system. If you're using Windows, -you can certainly use the run of the mill MS-DOS prompt, or you can use -GitBash, which will be installed if you used the link from above. +That's all we are going to cover in this section in regards to npm and semantic +version, but there is a lot more information about this on the npm [semver](https://docs.npmjs.com/misc/semver) +page if you'd like to dive into it a little deeper. ## Next lesson... -That's all the tools that we'll need to get started! So let's move on to -the next section and figure out what this NPM thing is... - +Let's get our development environment setup so we can finally get started +with some code... From 0d2679abf5247b2ab5d25b0d11eddf0503f0456b Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 09:40:10 -0800 Subject: [PATCH 06/34] Minor update --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 28212f8..2a9392c 100644 --- a/readme.md +++ b/readme.md @@ -10,7 +10,7 @@ JavaScript packages without the old copy and paste that we used to have to do back in the "old days". Application requirements are defined in a file that typically lives in the -root directory of your application called package.json: +root directory of your application called `package.json`: ```json { From 065c44e3405e8f881980a68c2e0098421f87fcb4 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 09:42:52 -0800 Subject: [PATCH 07/34] Reword dependencies section --- readme.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index 2a9392c..f334bd2 100644 --- a/readme.md +++ b/readme.md @@ -47,12 +47,11 @@ root directory of your application called `package.json`: } ``` -As you can see, the `package.json` files not only specifically says what -JavaScript modules we need to run our application in the `dependencies` -section, but it also includes the modules that aren't needed at run-time, -but we need in order to develop our application, in the `devDependencies` -section. It also includes some ancillary information that is needed if we -are going to push our package up to npm. +There are two major sections where we define our dependencies: `dependencies` +and `devDependencies`. The `dependencies` section defines everything that +our app needs during *run time*, while the `devDependencies` section defines +all of the modules we need during *development*. It also includes some +ancillary information that is needed if we are going to push our package up to npm. Let's now dive into what some of the weird characters and squiggly lines that you see in front of some of the version numbers mean. From 0a8becf5d6d74684ba094b2964250d27a58a8605 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 09:49:58 -0800 Subject: [PATCH 08/34] Add a few more headers and reword a few things --- readme.md | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index f334bd2..c4b20de 100644 --- a/readme.md +++ b/readme.md @@ -9,6 +9,8 @@ npm makes it really easy to install, and maintain specific versions of JavaScript packages without the old copy and paste that we used to have to do back in the "old days". +## Dependencies + Application requirements are defined in a file that typically lives in the root directory of your application called `package.json`: @@ -53,12 +55,23 @@ our app needs during *run time*, while the `devDependencies` section defines all of the modules we need during *development*. It also includes some ancillary information that is needed if we are going to push our package up to npm. -Let's now dive into what some of the weird characters and squiggly lines -that you see in front of some of the version numbers mean. +## Semantic Versioning + +npm uses [semantic versioning](http://semver.org/) in all of their modules +to make is easier to get the newest version of a module without breaking +your application code. They also have their own set of conventions and +special characters that are used in `package.json` dependencies to allow you +more fine grained control over how package versions are selected and installed. + + +## [Ranges](https://docs.npmjs.com/misc/semver#ranges) We'll start with the more obvious `>=`. It simply means "install the newest -version of this package that has at least this version number". Nothing too -ground breaking there, but what about this squiggly line business? +version of this package that has at least this version number". You can also +use other operators such as `>`, `<`, `=`, and `<=`. They all do exactly what +you think they do. Pretty simple eh? Well it doesn't end there... + +## [Tilde Ranges](https://docs.npmjs.com/misc/semver#tilde-ranges-1-2-3-1-2-1) Let's take a look at the `history` entry in our `package.json` file: ```json @@ -81,6 +94,8 @@ one more level of versioning in our dependency: the rules change yet again. Here, npm will accept any version that is greater than or equal to `1.0` and less than or equal to `2.0`. +## [Caret Ranges](https://docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4) + Next we'll take a quick peek at the [caret ranges](https://docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4) that are seen in our `package.json` file: ```json From 0d575afa17d9b11750fabb2d53febe7b90f621e5 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 09:54:59 -0800 Subject: [PATCH 09/34] Update caret range section --- readme.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index c4b20de..f5295ea 100644 --- a/readme.md +++ b/readme.md @@ -112,10 +112,13 @@ doesn't have a breaking change". Typically when a package author using [semver](https://docs.npmjs.com/misc/semver) makes a relatively minor, but breaking change to their module, they will bump the minor version. So a `0.1.x` package will become `0.2.0`. Let's say that we had a package that was -at version `0.1.3` and we were using caret ranges. During installation npm -finds two newer version of this package: `0.1.4` and `0.2.0`. Because we specified -a carat range, npm will select the `0.1.4` version. - +at version `0.1.3` and we were using caret ranges. Our `package.json` might +look like this: +```json +"sass-loader": "^0.1" +``` +During installation npm finds two newer version of this package: `0.1.4` and +`0.2.0`. Because we specified a carat range, npm will select the `0.1.4` version. That's all we are going to cover in this section in regards to npm and semantic version, but there is a lot more information about this on the npm [semver](https://docs.npmjs.com/misc/semver) From 3ae341befb23b384acdcfac777316acce5c8da40 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 11:20:33 -0800 Subject: [PATCH 10/34] Initial commit for Lesson 1.4 --- readme.md | 370 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 256 insertions(+), 114 deletions(-) diff --git a/readme.md b/readme.md index f5295ea..b3d171b 100644 --- a/readme.md +++ b/readme.md @@ -1,130 +1,272 @@ -# What's this npm thing anyways? +# Development Environment -npm, commonly referred to as "node package manager" is just that. It's a package -manager for node. Although, npm does *not* stand for "node package manager". -I won't go into the details of that, but if you'd like to, you can read all -about it [here](https://docs.npmjs.com/misc/faq#if-npm-is-an-acronym-why-is-it-never-capitalized). +Let's get your development environment up and running so that we can start +writing some code shall we? -npm makes it really easy to install, and maintain specific versions of -JavaScript packages without the old copy and paste that we used to have to do -back in the "old days". +## NVM -## Dependencies +Unlike npm, nvm *is* an acronym and stands for what you think it does(no, not +nevermind), "Node Version Manager". NVM allows us to have multiple, self +contained, version of Node running on the same system. While not entirely +necessary, it is very handy when working on multiple projects that are running +different version of Node. It also makes it super easy to install newer +versions of Node, and since it seems like lately theres a new version released +every other week, it's a great tool to have. If you don't agree with any of +this, or just plain can't get it installed, feel free to skip this section, as +it's not *required* to complete this course. -Application requirements are defined in a file that typically lives in the -root directory of your application called `package.json`: +### OS X -```json -{ - "name": "My Cool App", - "version": "1.0.0", - "description": "The most awesome nebulous app ever made", - "author": "Tony Stark (https://github.com/i-am-fictitious)", - "license": "ISC", - "devDependencies": { - "react-hot-loader": "1.3.0", - "webpack": "1.12.6", - "webpack-dev-server": "1.12.1" - }, - "dependencies": { - "babel-cli": "6.2.0", - "babel-core": "6.1.21", - "babel-loader": "6.2.0", - "babel-polyfill": "^6.2.0", - "babel-preset-es2015": "6.1.18", - "babel-preset-react": "6.1.18", - "babel-preset-stage-0": "6.1.18", - "babel-runtime": "6.1.18", - "css-loader": "^0.23.0", - "express": "4.13.3", - "extract-text-webpack-plugin": "^0.9.1", - "history": "~1.13.1", - "node-sass": "^3.4.2", - "normalize.css": "^3.0.3", - "react": ">=0.14.2", - "react-dom": ">=0.14.2", - "sass-loader": "^3.1.2", - "style-loader": "^0.13.0" - } -} -``` - -There are two major sections where we define our dependencies: `dependencies` -and `devDependencies`. The `dependencies` section defines everything that -our app needs during *run time*, while the `devDependencies` section defines -all of the modules we need during *development*. It also includes some -ancillary information that is needed if we are going to push our package up to npm. - -## Semantic Versioning - -npm uses [semantic versioning](http://semver.org/) in all of their modules -to make is easier to get the newest version of a module without breaking -your application code. They also have their own set of conventions and -special characters that are used in `package.json` dependencies to allow you -more fine grained control over how package versions are selected and installed. - - -## [Ranges](https://docs.npmjs.com/misc/semver#ranges) - -We'll start with the more obvious `>=`. It simply means "install the newest -version of this package that has at least this version number". You can also -use other operators such as `>`, `<`, `=`, and `<=`. They all do exactly what -you think they do. Pretty simple eh? Well it doesn't end there... - -## [Tilde Ranges](https://docs.npmjs.com/misc/semver#tilde-ranges-1-2-3-1-2-1) - -Let's take a look at the `history` entry in our `package.json` file: -```json -"history": "~1.13.1" +The first thing to do is to ensure that you have XCode installed. So open up +your terminal and type: +```bash +$ xcode-select --install ``` -This is called [tilde ranges](https://docs.npmjs.com/misc/semver#tilde-ranges-1-2-3-1-2-1), -and means that it allows the version number to change based on whether or not -the patch or minor version number is specified. In our current setup, any -version greater than or equal to `1.13.1` or less than `1.14.0` will be -an acceptable package. Now, had we specified it this way: -```json -"history": "~1.13" +If it's already installed you'll get an error message that reads something like +this: +```bash +xcode-select: error: command line tools are already installed, use "Software Update" to install updates ``` -then the rules change. In this scenario, npm will accept anything that is -greater than or equal to `1.13.0` and less than `1.14.0`. Again, if we remove -one more level of versioning in our dependency: -```json -"history": "~1" +You're good to go and can move on. Otherwise, a window will pop up prompting +you to install XCode. Go ahead and click install and grab a cup of coffee +while it downloads and installs. + +### Linux + +On Linux, you need to make sure you have the `build-essential` and `libssl-dev` +packages installed: +```bash +$ apt-get install build-essential libssl-dev +``` + +Once those dependencies are installed, you can go ahead and run the install +script using either curl or wget: +```bash +$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash +$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash +``` + +After the install script runs all you have to do is source it from your shell: +```bash +$ . ~/.nvm/nvm.sh +``` + +To make it source nvm upon every login just add the following to your `~/.bashrc`, +`~/.profile`, or `~/.zshrc` file: +```bash +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm +``` + +That's it! NVM is now installed. For more information and troubleshooting help +visit the [NVM Homepage](https://github.com/creationix/nvm) + +### Windows + +I didn't forget about you Windows users. NVM is actually unavailable on Windows. +There are a few alternatives: + * [nvmw](https://github.com/hakobera/nvmw) + * [nvm-windows](https://github.com/coreybutler/nvm-windows) + * [nodist](https://github.com/marcelklehr/nodist) + +If any of these don't work well for you, don't worry about it, you can just +use one version of Node. + +## Installing Node + +For those of you who were able to install NVM, congratulations! Installing +Node is as easy as this: +```bash +$ nvm install 5.1.1 +``` + +That's it! So go ahead and install Node 5.1.1 and we'll be on our way! + +If you weren't able to install NVM, or are using Windows, just go to the +[Node.js](https://nodejs.org/en/) site and download the installer for the +latest version and install it. + +## Installing npm + +You're done already. npm is installed alongside Node. Woohoo! + +## Installing React + +Next we're going to go ahead and get React installed. As of React 0.14, it +is broken up into several modules. `React` and `ReactDOM` are the two major +ones, and what we will start with. + +But first we need to create a folder for our app so we have a place to store +all of this stuff. Go into whatever directory you like to store all of your code +in and make a new directory inside of that one: +```bash +$ mkdir react-reading-time +``` + +By the way, we'll be making a small reusable React component in this tutorial +that will show estimated reading time for an atricle. Neat eh? + +Now let's cd into that directory and create a boilerplate `package.json` file: +```bash +$ cd react-reading-time +$ npm init --yes +``` +Using the `--yes` flag just skips all prompts and uses the defaults to +initialize the `package.json` file. + +After this is done we can install `React` and `ReactDOM`: +```bash +$ npm install --save-dev react react-dom ``` -the rules change yet again. Here, npm will accept any version that is greater -than or equal to `1.0` and less than or equal to `2.0`. -## [Caret Ranges](https://docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4) +You'll notice that we added the `--save-dev` flag. This tells npm to add both of +those packages to the `devDependencies` section of our `package.json` file. +We're saving it as a development dependency because this little module will +likely be a part of a bigger application that will already have React installed. -Next we'll take a quick peek at the [caret ranges](https://docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4) -that are seen in our `package.json` file: +Great! React is now installed and all we need to do now is install a few more +packages and get our development server up and running! + +## Development server + +In order to get our development server up and running we're going to have to +install a few modules, and create a couple of new files. Let's start by +installing a few things. + +### Webpack + +We're going to use [Webpack](https://webpack.github.io/) to handle the +transpiling of our code from ES6 to ES5(via Babel), bundling of all of our +code into one nice package, and to run our hot-reloading development server. +If you aren't familiar with the term `hot-reloading`, it simply means that +any changes we make to our JavaScript or CSS files(that Webpack knows about +and is including in the bundle) will be automatically transpiled, updated +in the bundle, and hot reloaded in the browser without us having to reload +the webpage to see our changes. Now THAT is awesome stuff. + +Let's begin by installing Webpack. We will be installing Webpack globally +so that we have access to the Command Line Tools. We do that by using the +`-g` flag: +```bash +$ npm install -g webpack +``` + +#### Install Global?!?! + +Whoa, whoa, whoa, wait a minute. What's this `install global` stuff mean +anyways? Up until now we've been installing all of our packages locally, +meaning that npm fetches the modules, and installs them in the `/node_modules` +directory in the root of our app. This is great for modules that *only* our app +is dependent on, or modules that don't have a [CLI](https://en.wikipedia.org/wiki/Command-line_interface), +but for things like Webpack or Grunt this is necessary. + + +### Babel + +Ok now that we have that all cleared up let's move on and install all of the +Babel dependencies we will need: +```bash +$ npm install --save-dev babel babel-core babel-loader +``` + +Great! Babel and all of the dependencies related to Babel have been installed. +But wait a minute! At the end of the install npm complained in big bright red +letters: `UNMET PEER DEPENDENCY webpack@^1.0.0`. But we just installed Webpack +didn't we? We did! But if you'll remember we installed it globally. When npm +was resolving [peer dependencies](https://docs.npmjs.com/files/package.json#peerdependencies) +it detected that we didn't have Webpack installed anywhere in our `node_modules` +directory, and we don't, so let's install it locally now. +```bash +$ npm install --save-dev webpack +``` + +#### Peer Dependencies?!?! + +Wait up a second, now what's a peer dependency? Simply stated, it's a module +that has code that is needed for the parent module to run properly, but shouldn't +necessarily be included with the module. For instance, if you're writing a reusable +React component that you would like to publish on npm for the whole world to +use, it's not really a great idea to include React as a dependency. It's +inferred that the person using this module is already going to have React +installed in their project, and therefore not necessary to include in the +dependency tree. + +### Webpack Dev Server and React Hot Loader + +These are the two pieces that allow us to do the hot-reloading that we were +talking about earlier. Let's go ahead and install them: +```bash +$ npm install --save-dev webpack-dev-server react-hot-loader +``` + +### Configure the server + +In order to configure the server we're going to have to create a configuration +file for Webpack. This isn't a Webpack class, so I won't go into the details. +First create a directory for our example application, and create the config file: +```bash +$ mkdir example +$ cd example +$ touch webpack.config.js +``` + +Now open up that file and copy the following code in: ```json -"sass-loader": "^3.1.2" -``` -From npm: -> Allows changes that do not modify the left-most non-zero digit in -> the [major, minor, patch] tuple. In other words, this allows patch and minor -> updates for versions 1.0.0 and above, patch updates for versions 0.X >=0.1.0, -> and no updates for versions 0.0.X. - -Essentially, this means "give me the newest version of this package that -doesn't have a breaking change". Typically when a package author using -[semver](https://docs.npmjs.com/misc/semver) makes a relatively minor, but -breaking change to their module, they will bump the minor version. So a -`0.1.x` package will become `0.2.0`. Let's say that we had a package that was -at version `0.1.3` and we were using caret ranges. Our `package.json` might -look like this: +var webpack = require('webpack'); + +module.exports = { + entry: { + 'react-reading-time': [ + 'webpack-dev-server/client?http://localhost:8881/', + 'webpack/hot/only-dev-server', + './example/react-reading-time.jsx' + ] + }, + output: { + path: __dirname, + filename: "[name].js", + publicPath: 'http://localhost:8881/', + chunkFilename: '[id].chunk.js', + sourceMapFilename: '[name].map' + }, + resolve: { + extensions: ['', '.js', '.jsx', '.es6'], + modulesDirectories: ['node_modules'] + }, + module: { + loaders: [ + { test: /\.jsx$|\.es6$|\.js$/, loaders: ['react-hot', 'babel-loader?stage=0'], exclude: /node_modules/ }, + { test: /\.scss$|\.css$/, loader: 'style-loader!style!css!sass' }, + { test: /\.(jpe?g|png|gif)$/i, loader: 'url?limit=10000!img?progressive=true' } + ] + }, + plugins: [ + new webpack.NoErrorsPlugin() + ], + devtool: "eval-source-map" +}; +``` + +Awesome! We've got our Webpack configuration in place. Now let's add some scripting +commands to our `package.json` file so we can easily start it up. Open up `package.json` +and add the following line in the `scripts` object: ```json -"sass-loader": "^0.1" +"start": "webpack-dev-server --config ./example/webpack.config.js --hot --port 8881", +``` + +This will give us the `npm start` command which we can use to fire up our development +server. + +Now we can fire up our development server. Let's give it a shot: +```bash +$ npm start ``` -During installation npm finds two newer version of this package: `0.1.4` and -`0.2.0`. Because we specified a carat range, npm will select the `0.1.4` version. -That's all we are going to cover in this section in regards to npm and semantic -version, but there is a lot more information about this on the npm [semver](https://docs.npmjs.com/misc/semver) -page if you'd like to dive into it a little deeper. +You should see Webpack initialize and try to compile our bundle. It's going to +complain and tell you that it can't find `example/react-reading-time.jsx`, and +that's ok because we haven't created that file yet! We'll be doing that shortly! -## Next lesson... +## Next lesson..... -Let's get our development environment setup so we can finally get started -with some code... +Phew! After a whirlwind tour of npm and Webpack, we're ready to create a few +more files that we need to get our application going.... From c4fc4ecf358cb36b6e16dfa18ad8d7fef60017ef Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 11:27:28 -0800 Subject: [PATCH 11/34] Fix typos --- readme.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index b3d171b..f4a17de 100644 --- a/readme.md +++ b/readme.md @@ -5,9 +5,9 @@ writing some code shall we? ## NVM -Unlike npm, nvm *is* an acronym and stands for what you think it does(no, not +Unlike npm, NVM *is* an acronym and stands for what you think it does(no, not nevermind), "Node Version Manager". NVM allows us to have multiple, self -contained, version of Node running on the same system. While not entirely +contained, versions of Node running on the same system. While not entirely necessary, it is very handy when working on multiple projects that are running different version of Node. It also makes it super easy to install newer versions of Node, and since it seems like lately theres a new version released @@ -39,6 +39,8 @@ packages installed: $ apt-get install build-essential libssl-dev ``` +### Install NVM + Once those dependencies are installed, you can go ahead and run the install script using either curl or wget: ```bash @@ -211,7 +213,7 @@ $ touch webpack.config.js ``` Now open up that file and copy the following code in: -```json +```js var webpack = require('webpack'); module.exports = { @@ -251,7 +253,15 @@ Awesome! We've got our Webpack configuration in place. Now let's add some script commands to our `package.json` file so we can easily start it up. Open up `package.json` and add the following line in the `scripts` object: ```json -"start": "webpack-dev-server --config ./example/webpack.config.js --hot --port 8881", +"start": "webpack-dev-server --config ./example/webpack.config.js --hot --port 8881" +``` + +We won't be doing any testing in this tutorial, so go ahead and remove the "test" +line. Your `scripts` object should now look like this: +```json +"scripts": { + "start": "webpack-dev-server --config ./example/webpack.config.js --hot --port 8881" +} ``` This will give us the `npm start` command which we can use to fire up our development From 5f8e39c71a0e71dcd50f691c63c0de8300ae9e78 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 11:29:15 -0800 Subject: [PATCH 12/34] Add notes to web server section --- readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.md b/readme.md index f4a17de..55280ac 100644 --- a/readme.md +++ b/readme.md @@ -276,6 +276,9 @@ You should see Webpack initialize and try to compile our bundle. It's going to complain and tell you that it can't find `example/react-reading-time.jsx`, and that's ok because we haven't created that file yet! We'll be doing that shortly! +You can also visit `localhost:8881` and see the glorious web server in action. +Although there isn't much to see just yet... + ## Next lesson..... Phew! After a whirlwind tour of npm and Webpack, we're ready to create a few From 84c19195c3251844eed5acce1e4a48b9492d2d25 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 11:56:12 -0800 Subject: [PATCH 13/34] Initial commit for Lesson 1.5 --- readme.md | 310 ++++++++---------------------------------------------- 1 file changed, 42 insertions(+), 268 deletions(-) diff --git a/readme.md b/readme.md index 55280ac..fe570f0 100644 --- a/readme.md +++ b/readme.md @@ -1,285 +1,59 @@ -# Development Environment +# Application Structure -Let's get your development environment up and running so that we can start -writing some code shall we? +In this short lesson we'll just be creating a few folders and files that will +be necessary for us to get going on our application development. -## NVM +## Example App Files -Unlike npm, NVM *is* an acronym and stands for what you think it does(no, not -nevermind), "Node Version Manager". NVM allows us to have multiple, self -contained, versions of Node running on the same system. While not entirely -necessary, it is very handy when working on multiple projects that are running -different version of Node. It also makes it super easy to install newer -versions of Node, and since it seems like lately theres a new version released -every other week, it's a great tool to have. If you don't agree with any of -this, or just plain can't get it installed, feel free to skip this section, as -it's not *required* to complete this course. - -### OS X - -The first thing to do is to ensure that you have XCode installed. So open up -your terminal and type: -```bash -$ xcode-select --install -``` -If it's already installed you'll get an error message that reads something like -this: -```bash -xcode-select: error: command line tools are already installed, use "Software Update" to install updates -``` -You're good to go and can move on. Otherwise, a window will pop up prompting -you to install XCode. Go ahead and click install and grab a cup of coffee -while it downloads and installs. - -### Linux - -On Linux, you need to make sure you have the `build-essential` and `libssl-dev` -packages installed: -```bash -$ apt-get install build-essential libssl-dev -``` - -### Install NVM - -Once those dependencies are installed, you can go ahead and run the install -script using either curl or wget: -```bash -$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash -$ wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash -``` - -After the install script runs all you have to do is source it from your shell: -```bash -$ . ~/.nvm/nvm.sh -``` - -To make it source nvm upon every login just add the following to your `~/.bashrc`, -`~/.profile`, or `~/.zshrc` file: -```bash -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm +Let's create all the structure we need to get our example application going. +First we'll need our main HTML page that our React component is going to mount +to. Inside of the `example` directory create a file called `index.html` and +paste in this code: +```html + + + React Reading Time Example + + + +
+
+
+ + + ``` -That's it! NVM is now installed. For more information and troubleshooting help -visit the [NVM Homepage](https://github.com/creationix/nvm) +We're doing a few things here. First we're just pulling in BootStrap to give +us some easy to use styling. Next you'll notice we have a `div` with an id +of `react` on it. This is the container that we are going to use to mount +our React app on. -### Windows +The next thing I want to point out is the script tag at the bottom of the +file. This is where our transpiled React code gets loaded. It's being loaded +directly from the hot development server that we've setup. If you look into +the `webpack.config.js` file you can see on line 6 we have set it up to output +the contents of our build to `localhost:8881` and further down in the file +we're telling webpack to use the keys of the entry objects as the file name. +So our output file will be called `react-reading-time.js`. -I didn't forget about you Windows users. NVM is actually unavailable on Windows. -There are a few alternatives: - * [nvmw](https://github.com/hakobera/nvmw) - * [nvm-windows](https://github.com/coreybutler/nvm-windows) - * [nodist](https://github.com/marcelklehr/nodist) - -If any of these don't work well for you, don't worry about it, you can just -use one version of Node. - -## Installing Node - -For those of you who were able to install NVM, congratulations! Installing -Node is as easy as this: +Next we just need to make a directory to hold all of our source files for this +mini application: ```bash -$ nvm install 5.1.1 +$ mkdir src ``` -That's it! So go ahead and install Node 5.1.1 and we'll be on our way! - -If you weren't able to install NVM, or are using Windows, just go to the -[Node.js](https://nodejs.org/en/) site and download the installer for the -latest version and install it. - -## Installing npm +## Testing it out -You're done already. npm is installed alongside Node. Woohoo! - -## Installing React - -Next we're going to go ahead and get React installed. As of React 0.14, it -is broken up into several modules. `React` and `ReactDOM` are the two major -ones, and what we will start with. - -But first we need to create a folder for our app so we have a place to store -all of this stuff. Go into whatever directory you like to store all of your code -in and make a new directory inside of that one: -```bash -$ mkdir react-reading-time -``` - -By the way, we'll be making a small reusable React component in this tutorial -that will show estimated reading time for an atricle. Neat eh? - -Now let's cd into that directory and create a boilerplate `package.json` file: -```bash -$ cd react-reading-time -$ npm init --yes -``` -Using the `--yes` flag just skips all prompts and uses the defaults to -initialize the `package.json` file. - -After this is done we can install `React` and `ReactDOM`: -```bash -$ npm install --save-dev react react-dom -``` - -You'll notice that we added the `--save-dev` flag. This tells npm to add both of -those packages to the `devDependencies` section of our `package.json` file. -We're saving it as a development dependency because this little module will -likely be a part of a bigger application that will already have React installed. - -Great! React is now installed and all we need to do now is install a few more -packages and get our development server up and running! - -## Development server - -In order to get our development server up and running we're going to have to -install a few modules, and create a couple of new files. Let's start by -installing a few things. - -### Webpack - -We're going to use [Webpack](https://webpack.github.io/) to handle the -transpiling of our code from ES6 to ES5(via Babel), bundling of all of our -code into one nice package, and to run our hot-reloading development server. -If you aren't familiar with the term `hot-reloading`, it simply means that -any changes we make to our JavaScript or CSS files(that Webpack knows about -and is including in the bundle) will be automatically transpiled, updated -in the bundle, and hot reloaded in the browser without us having to reload -the webpage to see our changes. Now THAT is awesome stuff. - -Let's begin by installing Webpack. We will be installing Webpack globally -so that we have access to the Command Line Tools. We do that by using the -`-g` flag: -```bash -$ npm install -g webpack -``` - -#### Install Global?!?! - -Whoa, whoa, whoa, wait a minute. What's this `install global` stuff mean -anyways? Up until now we've been installing all of our packages locally, -meaning that npm fetches the modules, and installs them in the `/node_modules` -directory in the root of our app. This is great for modules that *only* our app -is dependent on, or modules that don't have a [CLI](https://en.wikipedia.org/wiki/Command-line_interface), -but for things like Webpack or Grunt this is necessary. - - -### Babel - -Ok now that we have that all cleared up let's move on and install all of the -Babel dependencies we will need: -```bash -$ npm install --save-dev babel babel-core babel-loader -``` - -Great! Babel and all of the dependencies related to Babel have been installed. -But wait a minute! At the end of the install npm complained in big bright red -letters: `UNMET PEER DEPENDENCY webpack@^1.0.0`. But we just installed Webpack -didn't we? We did! But if you'll remember we installed it globally. When npm -was resolving [peer dependencies](https://docs.npmjs.com/files/package.json#peerdependencies) -it detected that we didn't have Webpack installed anywhere in our `node_modules` -directory, and we don't, so let's install it locally now. -```bash -$ npm install --save-dev webpack -``` - -#### Peer Dependencies?!?! - -Wait up a second, now what's a peer dependency? Simply stated, it's a module -that has code that is needed for the parent module to run properly, but shouldn't -necessarily be included with the module. For instance, if you're writing a reusable -React component that you would like to publish on npm for the whole world to -use, it's not really a great idea to include React as a dependency. It's -inferred that the person using this module is already going to have React -installed in their project, and therefore not necessary to include in the -dependency tree. - -### Webpack Dev Server and React Hot Loader - -These are the two pieces that allow us to do the hot-reloading that we were -talking about earlier. Let's go ahead and install them: -```bash -$ npm install --save-dev webpack-dev-server react-hot-loader -``` - -### Configure the server - -In order to configure the server we're going to have to create a configuration -file for Webpack. This isn't a Webpack class, so I won't go into the details. -First create a directory for our example application, and create the config file: -```bash -$ mkdir example -$ cd example -$ touch webpack.config.js -``` - -Now open up that file and copy the following code in: -```js -var webpack = require('webpack'); - -module.exports = { - entry: { - 'react-reading-time': [ - 'webpack-dev-server/client?http://localhost:8881/', - 'webpack/hot/only-dev-server', - './example/react-reading-time.jsx' - ] - }, - output: { - path: __dirname, - filename: "[name].js", - publicPath: 'http://localhost:8881/', - chunkFilename: '[id].chunk.js', - sourceMapFilename: '[name].map' - }, - resolve: { - extensions: ['', '.js', '.jsx', '.es6'], - modulesDirectories: ['node_modules'] - }, - module: { - loaders: [ - { test: /\.jsx$|\.es6$|\.js$/, loaders: ['react-hot', 'babel-loader?stage=0'], exclude: /node_modules/ }, - { test: /\.scss$|\.css$/, loader: 'style-loader!style!css!sass' }, - { test: /\.(jpe?g|png|gif)$/i, loader: 'url?limit=10000!img?progressive=true' } - ] - }, - plugins: [ - new webpack.NoErrorsPlugin() - ], - devtool: "eval-source-map" -}; -``` - -Awesome! We've got our Webpack configuration in place. Now let's add some scripting -commands to our `package.json` file so we can easily start it up. Open up `package.json` -and add the following line in the `scripts` object: -```json -"start": "webpack-dev-server --config ./example/webpack.config.js --hot --port 8881" -``` - -We won't be doing any testing in this tutorial, so go ahead and remove the "test" -line. Your `scripts` object should now look like this: -```json -"scripts": { - "start": "webpack-dev-server --config ./example/webpack.config.js --hot --port 8881" -} -``` - -This will give us the `npm start` command which we can use to fire up our development -server. - -Now we can fire up our development server. Let's give it a shot: +You can now fire up the development server again and test this small piece out! ```bash $ npm start ``` -You should see Webpack initialize and try to compile our bundle. It's going to -complain and tell you that it can't find `example/react-reading-time.jsx`, and -that's ok because we haven't created that file yet! We'll be doing that shortly! - -You can also visit `localhost:8881` and see the glorious web server in action. -Although there isn't much to see just yet... +Go ahead and visit `localhost:8881/example`. It's not much, just an empty +page, but we now have the skeleton we need to get started! -## Next lesson..... +## Next lesson.... -Phew! After a whirlwind tour of npm and Webpack, we're ready to create a few -more files that we need to get our application going.... +Next we'll move on to the next section of this tutorial, where we'll create +our first React component. From 7e4da41745caad9e9ca712d7ac3115acbc974d7c Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 20:04:43 -0800 Subject: [PATCH 14/34] Initial commit for Lesson 2.1 --- readme.md | 133 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 50 deletions(-) diff --git a/readme.md b/readme.md index fe570f0..b18d397 100644 --- a/readme.md +++ b/readme.md @@ -1,59 +1,92 @@ -# Application Structure - -In this short lesson we'll just be creating a few folders and files that will -be necessary for us to get going on our application development. - -## Example App Files - -Let's create all the structure we need to get our example application going. -First we'll need our main HTML page that our React component is going to mount -to. Inside of the `example` directory create a file called `index.html` and -paste in this code: -```html - - - React Reading Time Example - - - -
-
-
- - - +# Your first React Component + +Hooray! If you've made it this far, you're ready to do some serious coding +in React. Congratulations! + +## React components and ES6 + +We're going to be writing all of our React components using ES6. What this means +is that all of our components will be ES6 Classes. + +From [es6features](https://github.com/lukehoban/es6features#classes) on GitHub: + +> ES6 classes are a simple sugar over the prototype-based OO pattern. Having a +> single convenient declarative form makes class patterns easier to use, and +> encourages interoperability. Classes support prototype-based inheritance, +> super calls, instance and static methods and constructors. + +By convention, all React components that are created this way *must* inherit +from the `React.Component` class. Let's make a new file in our `example` directory +called `react-reading-time.jsx` and add some code to it. + +The first thing we need to do is import both the `React` and `ReactDOM` classes. +Add these lines to the top of that file: +```es6 +import React from 'react' +import ReactDOM from 'react-dom' ``` -We're doing a few things here. First we're just pulling in BootStrap to give -us some easy to use styling. Next you'll notice we have a `div` with an id -of `react` on it. This is the container that we are going to use to mount -our React app on. - -The next thing I want to point out is the script tag at the bottom of the -file. This is where our transpiled React code gets loaded. It's being loaded -directly from the hot development server that we've setup. If you look into -the `webpack.config.js` file you can see on line 6 we have set it up to output -the contents of our build to `localhost:8881` and further down in the file -we're telling webpack to use the keys of the entry objects as the file name. -So our output file will be called `react-reading-time.js`. - -Next we just need to make a directory to hold all of our source files for this -mini application: -```bash -$ mkdir src +It's conventional to include all `import` statements at the top of your file, +as you can't use anything until you've imported it(plus it makes your component +files much more neatly organized, and we all want to be good coders and make our +code nicely organized and easy for other developers to read). + +Ok great. Now we've imported the React modules that we'll need, let's start creating +our component. + +Wait a minute! What's the difference between `React` and `ReactDOM`?!?! With the +most recent release of React, the team over at Facebook decided to split up the +core application logic and the rendering logic. This decision was largely based +on the creation of `react-native` and the need for a cross platform rendering +engine. + +So let's go ahead and get started with our component. Let's add the core of +the component: +```es6 +class ReactReadingTime extends React.Component { + render() { + return
Hello React!
+ } +} ``` -## Testing it out +Awesome! But what's going on here? As I stated before, **EVERY** React component +must inherit from the `React.Component` class, and that's what we're doing here. +Also, *EVERY* React component must have a `render` method that returns the +JSX to be rendered on the page. + +Here we go again with these weird terms. What's JSX? Let's take a small detour +and talk about what the heck this JSX thing is. + +### JSX -You can now fire up the development server again and test this small piece out! -```bash -$ npm start +Facebook says: +> [JSX](https://facebook.github.io/jsx/) is a JavaScript syntax extension that +> looks similar to XML. You can use a simple JSX syntactic transform with React. + +Without using JSX, the markup for the component that we just created would +look like this: +```js +React.createElement('div', {className: "container"}, + "Hello React!" +) ``` -Go ahead and visit `localhost:8881/example`. It's not much, just an empty -page, but we now have the skeleton we need to get started! +Under the covers, this JSX gets transpiled and ends up looking like that, but +let's face it, the JSX syntax is **MUCH** nicer to work with. + +### Rendering the component -## Next lesson.... +This is where the `ReactDOM` class comes in. It's time for use to put it to +use to render our component. At the very bottom of the file, add this: +```es6 +ReactDOM.render(, document.getElementById('react')) +``` -Next we'll move on to the next section of this tutorial, where we'll create -our first React component. +When using the `render` function, the first argument is the component you would +like to render. In this case it's our main app component that we just created +called `ReactReadingTime`. The second argument is the DOM node that you would +like to attach the component to. Remember in our `index.html` file we created +that `div` with an id of 'react'. Well that's where this component is going to +mount. Save this file and let's reload our page at `localhost:8881/example` +and see what we've got! From 904e80a79b58d1ed5a65dc054e448c0ace0f5422 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 5 Dec 2015 20:29:38 -0800 Subject: [PATCH 15/34] Remove JSX from lesson --- readme.md | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/readme.md b/readme.md index b18d397..51fb824 100644 --- a/readme.md +++ b/readme.md @@ -45,7 +45,11 @@ the component: ```es6 class ReactReadingTime extends React.Component { render() { - return
Hello React!
+ return ( + React.createElement('div', {className: "container"}, + "Hello React!" + ) + ) } } ``` @@ -53,27 +57,7 @@ class ReactReadingTime extends React.Component { Awesome! But what's going on here? As I stated before, **EVERY** React component must inherit from the `React.Component` class, and that's what we're doing here. Also, *EVERY* React component must have a `render` method that returns the -JSX to be rendered on the page. - -Here we go again with these weird terms. What's JSX? Let's take a small detour -and talk about what the heck this JSX thing is. - -### JSX - -Facebook says: -> [JSX](https://facebook.github.io/jsx/) is a JavaScript syntax extension that -> looks similar to XML. You can use a simple JSX syntactic transform with React. - -Without using JSX, the markup for the component that we just created would -look like this: -```js -React.createElement('div', {className: "container"}, - "Hello React!" -) -``` - -Under the covers, this JSX gets transpiled and ends up looking like that, but -let's face it, the JSX syntax is **MUCH** nicer to work with. +React element to be rendered on the page. ### Rendering the component @@ -90,3 +74,8 @@ like to attach the component to. Remember in our `index.html` file we created that `div` with an id of 'react'. Well that's where this component is going to mount. Save this file and let's reload our page at `localhost:8881/example` and see what we've got! + +## Next lesson... + +Let's move on and discuss what JSX is and how it can help us create nicer +looking components. From 48e72e68a222abc275955b3a974ae7431781b312 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sun, 6 Dec 2015 13:14:26 -0800 Subject: [PATCH 16/34] Initial commit for Lesson 2.2 --- readme.md | 154 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 94 insertions(+), 60 deletions(-) diff --git a/readme.md b/readme.md index 51fb824..2c66b2b 100644 --- a/readme.md +++ b/readme.md @@ -1,81 +1,115 @@ -# Your first React Component +# JSX and you... -Hooray! If you've made it this far, you're ready to do some serious coding -in React. Congratulations! +## What is JSX? -## React components and ES6 +Put simply, **JSX allows you to create JavaScript objects using HTML syntax.** +Expanding on that, Facebook says: +> [JSX](https://facebook.github.io/jsx/) is a JavaScript syntax extension that +> looks similar to XML. You can use a simple JSX syntactic transform with React. -We're going to be writing all of our React components using ES6. What this means -is that all of our components will be ES6 Classes. +Remember in the last lesson we created our first component? The render +method looked like this: +```es6 +render() { + return ( + React.createElement('div', { className: 'container' }, + 'Hello React!' + ) + ) +} +``` -From [es6features](https://github.com/lukehoban/es6features#classes) on GitHub: +We can use JSX to transform that render method to look like this: +```es6 +render() { + return ( +
+ Hello React! +
+ ) +} +``` -> ES6 classes are a simple sugar over the prototype-based OO pattern. Having a -> single convenient declarative form makes class patterns easier to use, and -> encourages interoperability. Classes support prototype-based inheritance, -> super calls, instance and static methods and constructors. +## Why use JSX? -By convention, all React components that are created this way *must* inherit -from the `React.Component` class. Let's make a new file in our `example` directory -called `react-reading-time.jsx` and add some code to it. +There are several great reason for using JSX over the JavaScript syntax for +creating React views. More casual developers like designers will be much more +confortable with JSX, as it is easily regocnizable as HTML. Also, because JSX +has opening and closing tags like HTML, it makes large trees of UI components +much, much easier to read and reason about. -The first thing we need to do is import both the `React` and `ReactDOM` classes. -Add these lines to the top of that file: -```es6 -import React from 'react' -import ReactDOM from 'react-dom' +## Rendering JSX + +React can render either HTML tags or React components. There is an important +distinction to make however. If you use lowercase letters React will render +an html tag. So the following: +```jsx +ReactDOM.render(
, document.getElementById('react')) ``` -It's conventional to include all `import` statements at the top of your file, -as you can't use anything until you've imported it(plus it makes your component -files much more neatly organized, and we all want to be good coders and make our -code nicely organized and easy for other developers to read). +Will render the following in the DOM: +```html +
+``` -Ok great. Now we've imported the React modules that we'll need, let's start creating -our component. +However, when you use a **capitalized** tag name when rendering, React will +attempt to render a component with that name: +```jsx +ReactDOM.render(, document.getElementById('react')) +``` -Wait a minute! What's the difference between `React` and `ReactDOM`?!?! With the -most recent release of React, the team over at Facebook decided to split up the -core application logic and the rendering logic. This decision was largely based -on the creation of `react-native` and the need for a cross platform rendering -engine. +The above code will render the `MyComponent` class and all of it's children. -So let's go ahead and get started with our component. Let's add the core of -the component: -```es6 -class ReactReadingTime extends React.Component { - render() { - return ( - React.createElement('div', {className: "container"}, - "Hello React!" - ) - ) - } -} +## HTML attributes in JSX + +You may have noticed that in our above examples we're using `className` +instead of `class` in our HTML markup. Because JSX is just JavaScript, +we have to avoid using reserved identifiers such as `class` and `for` in +our JSX. Instead, we have to use name like `className` and `htmlFor` respectively +for these attributes. + +For a more complete list of JSX gotchas check here: +https://facebook.github.io/react/docs/jsx-gotchas.html + +And for a list of differences between JSX and the DOM check here: +https://facebook.github.io/react/docs/dom-differences.html + +## JavaScript Expressions + +It's absolutely possible and acceptable to use JavaScript expressions inside +of JSX. + +### Attribute Expressions + +If you'd like some logic inside one of your JSX attributes, simply wrap it in +curly braces `{}`: +```jsx +
``` -Awesome! But what's going on here? As I stated before, **EVERY** React component -must inherit from the `React.Component` class, and that's what we're doing here. -Also, *EVERY* React component must have a `render` method that returns the -React element to be rendered on the page. +### Boolean attributes -### Rendering the component +If the value of an attribute is omitted, it is assumed to be true, so the +following are equivalent: +```jsx + + +``` -This is where the `ReactDOM` class comes in. It's time for use to put it to -use to render our component. At the very bottom of the file, add this: -```es6 -ReactDOM.render(, document.getElementById('react')) +### Child expressions + +You can also use JavaScript expressions to render children: +```jsx + ``` -When using the `render` function, the first argument is the component you would -like to render. In this case it's our main app component that we just created -called `ReactReadingTime`. The second argument is the DOM node that you would -like to attach the component to. Remember in our `index.html` file we created -that `div` with an id of 'react'. Well that's where this component is going to -mount. Save this file and let's reload our page at `localhost:8881/example` -and see what we've got! +## Wrapping up + +JSX is awesome! It allows you to create and render complex components with all +the ease of writing basic HTML. Good stuff! ## Next lesson... -Let's move on and discuss what JSX is and how it can help us create nicer -looking components. +Now that we know our way around JSX, let's move on to a short discussion of a +few React conventions that most developers use shall we? + From 6542891e4bdc05d50a077482657eb90251023322 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sun, 6 Dec 2015 13:30:21 -0800 Subject: [PATCH 17/34] Initial commit for lesson2.3 --- readme.md | 152 +++++++++++++++++++++++++----------------------------- 1 file changed, 71 insertions(+), 81 deletions(-) diff --git a/readme.md b/readme.md index 2c66b2b..9039ad4 100644 --- a/readme.md +++ b/readme.md @@ -1,115 +1,105 @@ -# JSX and you... +# React conventions -## What is JSX? +We've already discussed some React conventions like using `className` in JSX +attributes. We're going to expand on that briefly just to give you a quick +overview of how developers in the community organize their code and write +reusable components. -Put simply, **JSX allows you to create JavaScript objects using HTML syntax.** -Expanding on that, Facebook says: -> [JSX](https://facebook.github.io/jsx/) is a JavaScript syntax extension that -> looks similar to XML. You can use a simple JSX syntactic transform with React. +## propTypes -Remember in the last lesson we created our first component? The render -method looked like this: -```es6 -render() { - return ( - React.createElement('div', { className: 'container' }, - 'Hello React!' - ) - ) +We'll go into this in more detail in the next section, but React provides a +`propTypes` declaration that you can, and **should** use to define what props +a component should receive, and their types: +```jsx +propTypes = { + foo: React.PropTypes.boolean, + bar: React.PropTypes.string } ``` -We can use JSX to transform that render method to look like this: -```es6 -render() { - return ( -
- Hello React! -
- ) -} -``` +This really helps your code to be self documenting, and will help future +developers out a lot when it's time for them to work on your codebase. -## Why use JSX? +## JSX structure -There are several great reason for using JSX over the JavaScript syntax for -creating React views. More casual developers like designers will be much more -confortable with JSX, as it is easily regocnizable as HTML. Also, because JSX -has opening and closing tags like HTML, it makes large trees of UI components -much, much easier to read and reason about. +Making your JSX well formed and structured is essential to writing clean, +easy to read code. -## Rendering JSX +### Multi-line components -React can render either HTML tags or React components. There is an important -distinction to make however. If you use lowercase letters React will render -an html tag. So the following: -```jsx -ReactDOM.render(
, document.getElementById('react')) -``` +It's good practice to keep JSX elements on separate lines in nested components. -Will render the following in the DOM: -```html -
+This is bad: +```jsx +
``` -However, when you use a **capitalized** tag name when rendering, React will -attempt to render a component with that name: +This is better: ```jsx -ReactDOM.render(, document.getElementById('react')) +
+ + +
``` -The above code will render the `MyComponent` class and all of it's children. - -## HTML attributes in JSX - -You may have noticed that in our above examples we're using `className` -instead of `class` in our HTML markup. Because JSX is just JavaScript, -we have to avoid using reserved identifiers such as `class` and `for` in -our JSX. Instead, we have to use name like `className` and `htmlFor` respectively -for these attributes. - -For a more complete list of JSX gotchas check here: -https://facebook.github.io/react/docs/jsx-gotchas.html +See how much easier to read and reason about the second version is? Always +put your conponents on their own lines. -And for a list of differences between JSX and the DOM check here: -https://facebook.github.io/react/docs/dom-differences.html +### Conditional elements -## JavaScript Expressions +If you have elements that will be rendered only if a specific condition is +met, then it's best practice to define those elements in a variable rather +than putting them inline in the JSX. -It's absolutely possible and acceptable to use JavaScript expressions inside -of JSX. - -### Attribute Expressions - -If you'd like some logic inside one of your JSX attributes, simply wrap it in -curly braces `{}`: +Bad: ```jsx -
+render() { + return ( +
+ { window.loggedIn? ? : null } +
+ ) +} ``` -### Boolean attributes - -If the value of an attribute is omitted, it is assumed to be true, so the -following are equivalent: +Good: ```jsx - - +render() { + let secretComponent + if (window.loggedIn?) secretComponent = + + return ( +
+ {secretComponent} +
+ ) +} ``` -### Child expressions +Again, much nicer, easier to read and reason about. This is only a simple +contrived example, but you can imagine with more complicated state and +components this could get really ugly. -You can also use JavaScript expressions to render children: +### Component attribute indentation + +When there are more than 3 or so attributes on a component, it is a good +idea to move them to their own line and use indentation to keep them +organized: ```jsx - + ``` ## Wrapping up -JSX is awesome! It allows you to create and render complex components with all -the ease of writing basic HTML. Good stuff! +This is by no means an exhaustive list of best practices and conventions, +but it will get you started on writing good, clean, reusable, maintainable, +and fun React components. ## Next lesson... -Now that we know our way around JSX, let's move on to a short discussion of a -few React conventions that most developers use shall we? - +Next we'll move on to section three and begin writing the component that +is going to make this application work! From 73e3625d6de3dfe5e5cd4160acfeef18fba07fe7 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sun, 6 Dec 2015 14:29:59 -0800 Subject: [PATCH 18/34] Initial commit for Lesson 3.1 --- readme.md | 188 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 117 insertions(+), 71 deletions(-) diff --git a/readme.md b/readme.md index 9039ad4..efc70ec 100644 --- a/readme.md +++ b/readme.md @@ -1,105 +1,151 @@ -# React conventions +# The ReadingTime component -We've already discussed some React conventions like using `className` in JSX -attributes. We're going to expand on that briefly just to give you a quick -overview of how developers in the community organize their code and write -reusable components. +Now it's time to start building our main component that will make this +application do something! WooHoo! -## propTypes +## Props + +Up until now we've used the word `props` here and there, but what really +are these mystical things called `props`? Props are simply properties that +are passed into a React component for consumption by said component. -We'll go into this in more detail in the next section, but React provides a -`propTypes` declaration that you can, and **should** use to define what props -a component should receive, and their types: ```jsx -propTypes = { - foo: React.PropTypes.boolean, - bar: React.PropTypes.string + +``` + +In that short snippet, `prop1` and `prop2` would be available to use in the +`Component` component. + +```jsx +class Component extends React.Component { + render() { + return ( +
+ {this.props.prop1} + {this.props.prop2} +
+ ) + } } ``` -This really helps your code to be self documenting, and will help future -developers out a lot when it's time for them to work on your codebase. +Easy right? Anything we give to the component as an "HTML attribute" is +available as a prop in the component. -## JSX structure +## propTypes -Making your JSX well formed and structured is essential to writing clean, -easy to read code. +We briefly discussed propTypes in the previous section, but let's put it to +use in real life for our new component. First, create a new file in the `src` +directory called `reading-time.jsx`. Let's import React and create the +skeleton for this component, remembering that there must **ALWAYS** be a render +function in the component. -### Multi-line components +```es6 +import React from 'react' -It's good practice to keep JSX elements on separate lines in nested components. +export default class ReadingTime extends React.Component { + static propTypes = {} -This is bad: -```jsx -
+ render() { + return ( +
+ ) + } +} ``` -This is better: +Ok great, now we've got an empty React component. The next thing we need to +do with it is define what propTypes this component will be expecting. One +thing that we will definitely need to know is how many words per minute we +expect people to be able to read. + +It looks like we're going to need a number property on this component in order +to be able to calculate the reading time. Let's go ahead and add this propType: ```jsx -
- - -
+static propTypes = { + wordsPerMinute: React.PropTypes.number +} ``` -See how much easier to read and reason about the second version is? Always -put your conponents on their own lines. +> Pro tip: React will raise a warning in the console if one of these props is +> missing or not the proper type, but will not raise an exception or cause +> your program to stop running. -### Conditional elements +## More ES6 syntax -If you have elements that will be rendered only if a specific condition is -met, then it's best practice to define those elements in a variable rather -than putting them inline in the JSX. +You might be asking yourself, what's with this `export default` and `static` +stuff? I thought you'd never ask. -Bad: -```jsx -render() { - return ( -
- { window.loggedIn? ? : null } -
- ) +Module support is baked into ES6, and we've already seen how we can *import* +code into a module that we need, but how do we get code *out* of a module +that we want to be available to other programs or our application? With +the `export` keyword of course! Any function, variable, or class that we +preced with `export` will be available when the module is imported from +other places in the application, but you have to explicitly ask for it: + +```es6 +export add = function(num1, num2) { + return num1 + num2 } ``` -Good: -```jsx -render() { - let secretComponent - if (window.loggedIn?) secretComponent = - - return ( -
- {secretComponent} -
- ) +Some time later, in a module far, far, away.... +```es6 +import MathFuncs from 'math' + +MatchFuncs.add(1, 2) +``` + +This is where the `export default` comes in. If you tell the module to export +something as the default, that's just what the variable name you define when +importing becomes, instead of the entire module: + +```es6 +export default function(num1, num2) { + return num1 + num2 } ``` -Again, much nicer, easier to read and reason about. This is only a simple -contrived example, but you can imagine with more complicated state and -components this could get really ugly. +Some time much later, in a module much, much farther away.... +```es6 +import add from 'math' -### Component attribute indentation +add(1, 2) +``` -When there are more than 3 or so attributes on a component, it is a good -idea to move them to their own line and use indentation to keep them -organized: -```jsx - +See the difference there? Typically in a React application, each component +module will export only the component class that is created, which is why +we define the class with the `export default` prefix. + +The static keyword is akin to class methods in other languages. It can be +used to define functions and variables that are available without creating +a new instance of the class: +```es6 +class MyClass { + static foo = 'This is very, very foo' +} + +MyClass.foo +-> This is very, very foo ``` -## Wrapping up +## defaultProps + +The next thing we're going want to address is default properties. We **should** +be able to use this component without anything actually being passed in as +props. We should define some sensible defaults that make it easy for people to +use the component without too much configuration. + +Add this to your component just below the propTypes declaration we just added: +```jsx +static defaultProps = { + wordsPerMinute: 270 +} +``` -This is by no means an exhaustive list of best practices and conventions, -but it will get you started on writing good, clean, reusable, maintainable, -and fun React components. +That's it! Now we have some sensible defaults that we can use in the event that +someone tries to use our component without giving it any props whatsoever. ## Next lesson... -Next we'll move on to section three and begin writing the component that -is going to make this application work! +Let's move on and start adding some state to our component. From 76fd334bdc5b4abcc6cc04ddba32472365ccbeb8 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sun, 6 Dec 2015 14:56:38 -0800 Subject: [PATCH 19/34] Initial commit for Lesson 3.2 --- readme.md | 218 +++++++++++++++++++++++++----------------------------- 1 file changed, 101 insertions(+), 117 deletions(-) diff --git a/readme.md b/readme.md index efc70ec..a956f0a 100644 --- a/readme.md +++ b/readme.md @@ -1,151 +1,135 @@ -# The ReadingTime component - -Now it's time to start building our main component that will make this -application do something! WooHoo! - -## Props +# Component constructors and state + +In React, props are immutable. Meaning you can't change the value of the props +once the component is created. So how do we got about creating dynamic UI's +that change? We use state. State is what represents what your application +UI looks like at any given moment. We define the initial state of our component +inside the constructor. What's a constructor?!?!?! It's the "initialize" +function for the class. Any time a new instance of the class is created, the +constructor is called and passed in any properties that are given during +initialization. +```es6 +export default class Component extends React.Component { + constructor(props) { + super(props) -Up until now we've used the word `props` here and there, but what really -are these mystical things called `props`? Props are simply properties that -are passed into a React component for consumption by said component. + this.state = props + } +} +``` +What's going on here? Every React component is initialized with props. So when +you create a component using JSX like this: ```jsx - + ``` -In that short snippet, `prop1` and `prop2` would be available to use in the -`Component` component. - -```jsx -class Component extends React.Component { - render() { - return ( -
- {this.props.prop1} - {this.props.prop2} -
- ) - } +The constructor of that `Component` class receives a JavaScript object literal +that looks like this: +```json +{ + foo: 'bar', + bar: 'baz' } ``` -Easy right? Anything we give to the component as an "HTML attribute" is -available as a prop in the component. - -## propTypes - -We briefly discussed propTypes in the previous section, but let's put it to -use in real life for our new component. First, create a new file in the `src` -directory called `reading-time.jsx`. Let's import React and create the -skeleton for this component, remembering that there must **ALWAYS** be a render -function in the component. - +The other thing you may find strange is the `super` function call. What this +does is it tells the class to call the inherited classes (in this case, the +React.Component) constructor function with the arguments you give it. When +using inherited classes it is require that the super method (if being called) +be called before anything else in the constructor. So here we're just passing +off the props to React and letting React do what it normally does with them. +In this case React will assign them to `this.props`. In this contrived example +we're also assigning the state of the application to the props. + +Now let's open up our `ReadingTime` component and add the following +constructor: ```es6 -import React from 'react' +constructor(props) { + super(props) -export default class ReadingTime extends React.Component { - static propTypes = {} - - render() { - return ( -
- ) + this.state = { + readTime: 0 } } ``` -Ok great, now we've got an empty React component. The next thing we need to -do with it is define what propTypes this component will be expecting. One -thing that we will definitely need to know is how many words per minute we -expect people to be able to read. - -It looks like we're going to need a number property on this component in order -to be able to calculate the reading time. Let's go ahead and add this propType: -```jsx -static propTypes = { - wordsPerMinute: React.PropTypes.number -} -``` - -> Pro tip: React will raise a warning in the console if one of these props is -> missing or not the proper type, but will not raise an exception or cause -> your program to stop running. - -## More ES6 syntax - -You might be asking yourself, what's with this `export default` and `static` -stuff? I thought you'd never ask. - -Module support is baked into ES6, and we've already seen how we can *import* -code into a module that we need, but how do we get code *out* of a module -that we want to be available to other programs or our application? With -the `export` keyword of course! Any function, variable, or class that we -preced with `export` will be available when the module is imported from -other places in the application, but you have to explicitly ask for it: - +For reference, your `ReadingTime` component should now look like this: ```es6 -export add = function(num1, num2) { - return num1 + num2 -} -``` +import React from 'react' -Some time later, in a module far, far, away.... -```es6 -import MathFuncs from 'math' +export default class ReadingTime extends React.Component { + static propTypes = { + wordsPerMinute: React.PropTypes.number + } -MatchFuncs.add(1, 2) -``` + static defaultProps = { + wordsPerMinute: 270 + } -This is where the `export default` comes in. If you tell the module to export -something as the default, that's just what the variable name you define when -importing becomes, instead of the entire module: + constructor(props) { + super(props) -```es6 -export default function(num1, num2) { - return num1 + num2 + this.state = { readTime: 0 } + } + + render() { + return ( +
Hello ReadingTime!
+ ) + } } ``` -Some time much later, in a module much, much farther away.... +Excellent! We've created another component! Let's open up our main application +component and add this component to our app. Open up `example/react-reading-time.jsx` +and import our component: ```es6 -import add from 'math' - -add(1, 2) +import ReadingTime from '../src/reading-time' ``` -See the difference there? Typically in a React application, each component -module will export only the component class that is created, which is why -we define the class with the `export default` prefix. - -The static keyword is akin to class methods in other languages. It can be -used to define functions and variables that are available without creating -a new instance of the class: +Ok now let's add this component to our view. We'll also add some classes, +a textarea for writing an article and some default text to put into the textarea. +Let's just rewrite the entire render function like this: ```es6 -class MyClass { - static foo = 'This is very, very foo' +render() { + let defaultText = 'Foo is baz and bar' + + return ( +
+
+ +
+ +
+ ) } - -MyClass.foo --> This is very, very foo ``` -## defaultProps - -The next thing we're going want to address is default properties. We **should** -be able to use this component without anything actually being passed in as -props. We should define some sensible defaults that make it easy for people to -use the component without too much configuration. +Woohoo! We've got our component set to render inside of our main application +page along with a text area. You'll notice a few things I did there that +may seem strange. The first one is adding a data attribute to the div that +holds the textarea. I did this so that later on down the road our `ReadingTime` +component will have a way to know which container to get the word count from. -Add this to your component just below the propTypes declaration we just added: -```jsx -static defaultProps = { - wordsPerMinute: 270 -} -``` +I also added a style attribute to the element, but it doesn't look like a normal +style tag that you would add to an HTML. Remember when we talked about JSX, +and how it's really just JavaScript? Because of that, we have to give the +style tag a regular old JavaScript object to work with, which it can then +turn into the proper style tag when rendering the DOM. -That's it! Now we have some sensible defaults that we can use in the event that -someone tries to use our component without giving it any props whatsoever. +Let's fire up the server again with `npm start` and visit `localhost:8881/example` +and see what we've created so far! It's getting more and more exciting by the +minute! ## Next lesson... -Let's move on and start adding some state to our component. +Next we're going to dive into the Virtual DOM and find out how it is that +React is so good at updating the UI based on the state of the component. From ab24dc1e75cca710df0fa3112acb959cbaeacfda Mon Sep 17 00:00:00 2001 From: dphaener Date: Sun, 6 Dec 2015 18:34:42 -0800 Subject: [PATCH 20/34] Initial commit for Lesson 3.3 --- readme.md | 165 ++++++++++++++---------------------------------------- 1 file changed, 42 insertions(+), 123 deletions(-) diff --git a/readme.md b/readme.md index a956f0a..949bc23 100644 --- a/readme.md +++ b/readme.md @@ -1,135 +1,54 @@ -# Component constructors and state - -In React, props are immutable. Meaning you can't change the value of the props -once the component is created. So how do we got about creating dynamic UI's -that change? We use state. State is what represents what your application -UI looks like at any given moment. We define the initial state of our component -inside the constructor. What's a constructor?!?!?! It's the "initialize" -function for the class. Any time a new instance of the class is created, the -constructor is called and passed in any properties that are given during -initialization. -```es6 -export default class Component extends React.Component { - constructor(props) { - super(props) - - this.state = props - } -} -``` - -What's going on here? Every React component is initialized with props. So when -you create a component using JSX like this: -```jsx - -``` - -The constructor of that `Component` class receives a JavaScript object literal -that looks like this: -```json -{ - foo: 'bar', - bar: 'baz' -} -``` - -The other thing you may find strange is the `super` function call. What this -does is it tells the class to call the inherited classes (in this case, the -React.Component) constructor function with the arguments you give it. When -using inherited classes it is require that the super method (if being called) -be called before anything else in the constructor. So here we're just passing -off the props to React and letting React do what it normally does with them. -In this case React will assign them to `this.props`. In this contrived example -we're also assigning the state of the application to the props. - -Now let's open up our `ReadingTime` component and add the following -constructor: -```es6 -constructor(props) { - super(props) - - this.state = { - readTime: 0 - } -} -``` - -For reference, your `ReadingTime` component should now look like this: +# The Virtaul DOM + +So up until now you may have been wondering how React can possibly manage +to update the state of your components? You may have also heard of this +magical sounding thing called the Virtual DOM. Well the Virtual DOM is how +React works it's magic. + +Imagine looking at all of the HTML markup on your page, and being able to +just take a snapshot of it in your memory, and just know when any little piece +of it has changed. That's essentially what the Virtual DOM is. + +When your application is initially rendered into the DOM, with it's initial +state, React takes a "snapshot" of this and holds it in memory. This is the +Virtual DOM. + +Any time a DOM update is triggered, React updates the Virtual DOM to reflect +the new state of the app. It then does what's called a DOM diff, and selects +only the pieces the DOM that have changed. It compares the Virtual DOM, with +the actual DOM, and only updates the parts of the DOM that have changed. + +This makes updating the application state extremely fast and efficient, as +we do not have to update the entire page to reflect the new state of the app. +Also, we, as developers, do not have to programatically get the reference to +the DOM node that needs to be updated, and then perform the update ourselves. +We simply change a variable in the state tree and let React do all the work +for us. + +## Putting it into practice + +Ok awesome. This is great. But let's see it in action. Do you remember when +we created the constructor for our component in the last lesson? We set +the initial state of the app: ```es6 -import React from 'react' - -export default class ReadingTime extends React.Component { - static propTypes = { - wordsPerMinute: React.PropTypes.number - } - - static defaultProps = { - wordsPerMinute: 270 - } - - constructor(props) { - super(props) - - this.state = { readTime: 0 } - } - - render() { - return ( -
Hello ReadingTime!
- ) - } +this.state = { + readTime: 0 } ``` -Excellent! We've created another component! Let's open up our main application -component and add this component to our app. Open up `example/react-reading-time.jsx` -and import our component: -```es6 -import ReadingTime from '../src/reading-time' -``` - -Ok now let's add this component to our view. We'll also add some classes, -a textarea for writing an article and some default text to put into the textarea. -Let's just rewrite the entire render function like this: +Let's use that state to display something in our widget. Update the render +method of your `ReadingTime` component to look like this: ```es6 render() { - let defaultText = 'Foo is baz and bar' - return ( -
-
- -
- +
+

+ Estimated Read Time:

+ {this.state.readTime} +

) } ``` -Woohoo! We've got our component set to render inside of our main application -page along with a text area. You'll notice a few things I did there that -may seem strange. The first one is adding a data attribute to the div that -holds the textarea. I did this so that later on down the road our `ReadingTime` -component will have a way to know which container to get the word count from. - -I also added a style attribute to the element, but it doesn't look like a normal -style tag that you would add to an HTML. Remember when we talked about JSX, -and how it's really just JavaScript? Because of that, we have to give the -style tag a regular old JavaScript object to work with, which it can then -turn into the proper style tag when rendering the DOM. - -Let's fire up the server again with `npm start` and visit `localhost:8881/example` -and see what we've created so far! It's getting more and more exciting by the -minute! - -## Next lesson... - -Next we're going to dive into the Virtual DOM and find out how it is that -React is so good at updating the UI based on the state of the component. +For the purposes of demonstration From 0be4b6b3680725bbb9d267ecb0557e5a141909a5 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sun, 6 Dec 2015 19:42:00 -0800 Subject: [PATCH 21/34] Initial commit for Lesson 3.4 --- readme.md | 203 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 164 insertions(+), 39 deletions(-) diff --git a/readme.md b/readme.md index 949bc23..5e20b6b 100644 --- a/readme.md +++ b/readme.md @@ -1,49 +1,130 @@ -# The Virtaul DOM - -So up until now you may have been wondering how React can possibly manage -to update the state of your components? You may have also heard of this -magical sounding thing called the Virtual DOM. Well the Virtual DOM is how -React works it's magic. - -Imagine looking at all of the HTML markup on your page, and being able to -just take a snapshot of it in your memory, and just know when any little piece -of it has changed. That's essentially what the Virtual DOM is. - -When your application is initially rendered into the DOM, with it's initial -state, React takes a "snapshot" of this and holds it in memory. This is the -Virtual DOM. - -Any time a DOM update is triggered, React updates the Virtual DOM to reflect -the new state of the app. It then does what's called a DOM diff, and selects -only the pieces the DOM that have changed. It compares the Virtual DOM, with -the actual DOM, and only updates the parts of the DOM that have changed. - -This makes updating the application state extremely fast and efficient, as -we do not have to update the entire page to reflect the new state of the app. -Also, we, as developers, do not have to programatically get the reference to -the DOM node that needs to be updated, and then perform the update ourselves. -We simply change a variable in the state tree and let React do all the work -for us. - -## Putting it into practice - -Ok awesome. This is great. But let's see it in action. Do you remember when -we created the constructor for our component in the last lesson? We set -the initial state of the app: +# Finishing the ReadingTime component + +We're going to go ahead and finish up the `ReadingTime` component in this +lesson and we'll see how updating state makes the UI update. + +First we'll need to add some boilerplate code that will count the actual +words inside of the textarea we created. This code is pretty boring, and +doesn't have anything to do with React, so we'll just paste it in: +```es6 +countWords(text) { + return text.split(/\s+/).length +} + +getText(domElement) { + let text = '', + length = domElement.childNodes.length + + for (var i = 0; i < length; i++) { + let el = domElement.childNodes[i] + + if (el.nodeType != 8) { + if (el.type && el.type.match(/(textarea|input)/)) { + text += el.value + } else { + text += el.nodeType === 3 ? el.nodeValue : this.getText(el) + } + } + } + + return text +} +``` + +Time for a quick rundown of these functions. The `getText` function simply traverses +all of the children of the selected DOM element that is passed into the function +and grabs all the text that is inside of them and concatenates it into one +long string. + +The `countWords` function simply takes a string, splits it wherever there is a +space and counts how many words there are. Nothing too exciting here, but we +will need these two functions to get our reading time estimator to work. + +## Component lifecycles + +The next thing we need to do is estimate what the reading time is going to be +for the article that is on the page when the component mounts. We can't +execute that code in the constructor of the component, because when the +component is created the DOM has not yet been rendered, so the word count +would always be zero. We're going to use React's lifecycle hooks to run +this code immediately after the DOM has been rendered. There are quite a few +lifecycle hooks available, and you can read all about them [here](https://facebook.github.io/react/docs/component-specs.html#lifecycle-methods). +For this use case, we'll be using the `componentDidMount` hook, so let's add +this to our `ReadingTime` component. React convention is to put this function +immediately after the constructor function and before any other code: ```es6 -this.state = { - readTime: 0 +componentDidMount() { + let selector = '[data-article]', + article = document.querySelector(selector), + text = this.getText(article), + wordCount = this.countWords(text), + readTime = Math.round(wordCount / this.props.wordsPerMinute) + + this.setState({ readTime: readTime }) } ``` -Let's use that state to display something in our widget. Update the render -method of your `ReadingTime` component to look like this: +Ok so what's happening here? The first thing we're doing is setting variable +equal to the DOM selector that we want to use to grab the chunk of the DOM +that contains the article we're interested in. Remember a few lessons ago +when we created the textarea, and the containing div had that data attribute +on it? That's why we put that there. + +So we're then selecting that element, passing that element into our `getText` +function to pull all the text from that container and dump it into a string, +which will then be assigned to the `text` variable. Then we're just passing +that into the `countWords` function to get the total word count and assign it +to the `wordCount` variable. Then it's just a matter of taking that total +wordcount and dividing it by the `wordsPerMinute` prop that we defined in an +earlier lesson. + +After we've calculated what the reading time is going to be for this article +it's as simple as setting the state! But we can't just simply update the value +of `this.state`. We really should treat the component state as if it is +immutable, and use React's internal methods to update the state. That's why +we use the `setState` method to set the state. Using this method also triggers +a DOM update, so React will update the Virtual DOM, perform the diff, and update +the pieces of the DOM that have changed. + +Up until now our component has always said that the reading time is 0. +Unfortunately, it's still going to, because we only have 5 words in our text +box. So go ahead and update the `defaultText` variable in the render method +of the `ReactReadingTime` component to something really, really long, and you +should see the estimated reading time jump up when the page loads. + +You'll notice that you have to refresh the page to get an updated value. This +is because the `componentDidMount` function will be called once, and only +once, when the component first mounts. Our hot loader just inserts new code +into the existing code, and does not cause the component to remount, so we +have to refresh the page. + +If you've done everything right it should work! You won't even see that initial +value of 0 on the page (although it is actually rendered initially) because +all of React's updating happens so very fast. + +## JSX Spread Operators + +We're going to add some classes to our component to help make it look just a +little bit prettier. + +If you'll recall from our `ReactReadingTime` component, when we rendered the +`ReadingTime` widget, we added some classes to it: +```jsx + +``` + +But if you inspect the DOM that it actually rendered, these class names are +nowhere to be found. This is because those class names are just passed into +our custom component as `this.props.className` and because we didn't do +anything with them, they just died there. + +We can do the following to add these classes to our markup: ```es6 render() { return ( -
+

- Estimated Read Time:

+ Estimated read time:

{this.state.readTime}

@@ -51,4 +132,48 @@ render() { } ``` -For the purposes of demonstration +And this will work just fine. The names of the classes in that prop will be +passed into that div and rendered into the DOM. But what if later we want to +expand this component and add more props? Then we have to add another attribute +to that div to pass the new props in. What if we decide to release this module +into the wild on npm and the end user wants to add custom attributes to this +component? That's where JSX spread operators come into play. With spread +operators we can rewrite that like this: +```es6 +render() { + let props = this.props + + return ( +
+ ... +
+ ) +} +``` + +What's going on there? What we're saying here is to take all the props and +apply them to that div. So if our props looked like this: +```json +{ + className: 'foo', + name: 'bar' +} +``` + +Then the component would end up looking like this: +```es6 +
+``` + +This allows us to pass in any number of arbitrary props to the component that +we as the module developers may never think of. It also saves a whole lot of +typing. :) Which makes for developer happiness. + +So if you update your code to use those spread operators, you should have a +nice well drawn around your reading time widget! We're getting there! + +## Next lesson... + +We've completed 3 sections in this tutorial and are ready to move on to the +final one and tie all of this together! We'll have a truly reactive application +and will do some great refactoring... Let's go!!! From 79466179d07d6182bed1bea84bd4f4337bdaede1 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sun, 6 Dec 2015 20:03:49 -0800 Subject: [PATCH 22/34] Initial commit for Lesson 4.1 --- readme.md | 216 +++++++++++++++++------------------------------------- 1 file changed, 67 insertions(+), 149 deletions(-) diff --git a/readme.md b/readme.md index 5e20b6b..e3bd772 100644 --- a/readme.md +++ b/readme.md @@ -1,179 +1,97 @@ -# Finishing the ReadingTime component +# Event Handlers -We're going to go ahead and finish up the `ReadingTime` component in this -lesson and we'll see how updating state makes the UI update. - -First we'll need to add some boilerplate code that will count the actual -words inside of the textarea we created. This code is pretty boring, and -doesn't have anything to do with React, so we'll just paste it in: +So far we've built our little app to count the number of words in an existing +article and display that in our widget. This works, but isn't very exciting +and doesn't respond to any changes on the page. Let's use some event handlers +to trigger updates on our `ReadingTime` widget. Open up the `ReactReadingTime` +component and add an `onChange` handler to the textarea. ```es6 -countWords(text) { - return text.split(/\s+/).length -} - -getText(domElement) { - let text = '', - length = domElement.childNodes.length - - for (var i = 0; i < length; i++) { - let el = domElement.childNodes[i] - - if (el.nodeType != 8) { - if (el.type && el.type.match(/(textarea|input)/)) { - text += el.value - } else { - text += el.nodeType === 3 ? el.nodeValue : this.getText(el) - } - } - } - - return text -} + ``` -Time for a quick rundown of these functions. The `getText` function simply traverses -all of the children of the selected DOM element that is passed into the function -and grabs all the text that is inside of them and concatenates it into one -long string. - -The `countWords` function simply takes a string, splits it wherever there is a -space and counts how many words there are. Nothing too exciting here, but we -will need these two functions to get our reading time estimator to work. - -## Component lifecycles - -The next thing we need to do is estimate what the reading time is going to be -for the article that is on the page when the component mounts. We can't -execute that code in the constructor of the component, because when the -component is created the DOM has not yet been rendered, so the word count -would always be zero. We're going to use React's lifecycle hooks to run -this code immediately after the DOM has been rendered. There are quite a few -lifecycle hooks available, and you can read all about them [here](https://facebook.github.io/react/docs/component-specs.html#lifecycle-methods). -For this use case, we'll be using the `componentDidMount` hook, so let's add -this to our `ReadingTime` component. React convention is to put this function -immediately after the constructor function and before any other code: +We've just updated the textarea to call a `textChanged` function any time the +textarea value changes. Ok, so now we need to implement this function. Let's +add this function at the top of our component: ```es6 -componentDidMount() { - let selector = '[data-article]', - article = document.querySelector(selector), - text = this.getText(article), - wordCount = this.countWords(text), - readTime = Math.round(wordCount / this.props.wordsPerMinute) +textChanged = () => { - this.setState({ readTime: readTime }) } ``` -Ok so what's happening here? The first thing we're doing is setting variable -equal to the DOM selector that we want to use to grab the chunk of the DOM -that contains the article we're interested in. Remember a few lessons ago -when we created the textarea, and the containing div had that data attribute -on it? That's why we put that there. +## Arrow functions -So we're then selecting that element, passing that element into our `getText` -function to pull all the text from that container and dump it into a string, -which will then be assigned to the `text` variable. Then we're just passing -that into the `countWords` function to get the total word count and assign it -to the `wordCount` variable. Then it's just a matter of taking that total -wordcount and dividing it by the `wordsPerMinute` prop that we defined in an -earlier lesson. +You may notice some funny looking syntax there. What's with this fat arrow +business `=>`? That's some ES6 syntactical sugar that automatically binds +that function to `this`. In this case `this` is the entire scopr of the +component. We run into trouble with `onChange` handlers like that, because +when the function is fired, it is in the scope of the `textarea` component, +and we need access to the global component scope. By using an arrow function +like that, we will now have access to the component's scope. Great! -After we've calculated what the reading time is going to be for this article -it's as simple as setting the state! But we can't just simply update the value -of `this.state`. We really should treat the component state as if it is -immutable, and use React's internal methods to update the state. That's why -we use the `setState` method to set the state. Using this method also triggers -a DOM update, so React will update the Virtual DOM, perform the diff, and update -the pieces of the DOM that have changed. +## Making the component update -Up until now our component has always said that the reading time is 0. -Unfortunately, it's still going to, because we only have 5 words in our text -box. So go ahead and update the `defaultText` variable in the render method -of the `ReactReadingTime` component to something really, really long, and you -should see the estimated reading time jump up when the page loads. - -You'll notice that you have to refresh the page to get an updated value. This -is because the `componentDidMount` function will be called once, and only -once, when the component first mounts. Our hot loader just inserts new code -into the existing code, and does not cause the component to remount, so we -have to refresh the page. - -If you've done everything right it should work! You won't even see that initial -value of 0 on the page (although it is actually rendered initially) because -all of React's updating happens so very fast. - -## JSX Spread Operators - -We're going to add some classes to our component to help make it look just a -little bit prettier. - -If you'll recall from our `ReactReadingTime` component, when we rendered the -`ReadingTime` widget, we added some classes to it: -```jsx - +Ok, so now we've trapped that onChange event, but what do we do with it? We +need to tell the `ReadingTime` component to update the word count when this +happens. But how do we communicate with it? React provides a way to do this +and it's called [refs](https://facebook.github.io/react/docs/more-about-refs.html). +We can add a "reference" to a component, and then access it's internal +methods form the parent component. Let's add a ref to the `ReadingTime` component" +```es6 + ``` -But if you inspect the DOM that it actually rendered, these class names are -nowhere to be found. This is because those class names are just passed into -our custom component as `this.props.className` and because we didn't do -anything with them, they just died there. - -We can do the following to add these classes to our markup: +So now that we have a reference to the component, we can tell it to update: ```es6 -render() { - return ( -
-

- Estimated read time:

- {this.state.readTime} -

-
- ) +textChanged = () => { + this.refs.readingTime.updateReadingTime() } ``` -And this will work just fine. The names of the classes in that prop will be -passed into that div and rendered into the DOM. But what if later we want to -expand this component and add more props? Then we have to add another attribute -to that div to pass the new props in. What if we decide to release this module -into the wild on npm and the end user wants to add custom attributes to this -component? That's where JSX spread operators come into play. With spread -operators we can rewrite that like this: +When you add a ref to a component, that component is then added to a `refs` +array on the parent component. So we can access it through `this.refs` and +then the name of the ref. At this point, we have the instance of the element +and call tell it to do whatever we want! Now we'll need to implement the +`updateReadingTime` function in the `ReadingTime` component. Go ahead and open +that file and let's add it: ```es6 -render() { - let props = this.props +updateReadingTime = () => { + let selector = '[data-article]', + article = document.querySelector(selector), + text = this.getText(article), + wordCount = this.countWords(text), + readTime = Math.round(wordCount / this.props.wordsPerMinute) - return ( -
- ... -
- ) + this.setState({ readTime: readTime }) } ``` -What's going on there? What we're saying here is to take all the props and -apply them to that div. So if our props looked like this: -```json -{ - className: 'foo', - name: 'bar' -} -``` +That's all we need to do! Now you be able to happily type away and the widget +will update automatically! Awesome stuff! Of course, because we need to add +270 words to make the reading time increase by 1 minute, it will take quite +a few words to make it update. To make it more responsive go ahead and update +the default `wordsPerMinute` to something much lower (like 1) and watch it +update right away. Just make sure you move it back up to 270. :) -Then the component would end up looking like this: +Let's update the `ReadingTime` widget to make the output look just a bit nicer: ```es6 -
+return ( +
+

+ Estimated read time:

+ {this.state.readTime} minutes +

+
+) ``` -This allows us to pass in any number of arbitrary props to the component that -we as the module developers may never think of. It also saves a whole lot of -typing. :) Which makes for developer happiness. - -So if you update your code to use those spread operators, you should have a -nice well drawn around your reading time widget! We're getting there! +All we did there was just add the word `minutes` at the end of the reading time +count. ## Next lesson... -We've completed 3 sections in this tutorial and are ready to move on to the -final one and tie all of this together! We'll have a truly reactive application -and will do some great refactoring... Let's go!!! +We're almost there! We just need to spend some time cleaning a few things up... From 71ee9f2501b797b6aeb20ca201f0bd5578d205df Mon Sep 17 00:00:00 2001 From: dphaener Date: Sun, 6 Dec 2015 20:18:11 -0800 Subject: [PATCH 23/34] Initial commit for Lesson 4.2 --- readme.md | 137 +++++++++++++++++++++++++----------------------------- 1 file changed, 63 insertions(+), 74 deletions(-) diff --git a/readme.md b/readme.md index e3bd772..664237c 100644 --- a/readme.md +++ b/readme.md @@ -1,97 +1,86 @@ -# Event Handlers +# Refactoring!! -So far we've built our little app to count the number of words in an existing -article and display that in our widget. This works, but isn't very exciting -and doesn't respond to any changes on the page. Let's use some event handlers -to trigger updates on our `ReadingTime` widget. Open up the `ReactReadingTime` -component and add an `onChange` handler to the textarea. +There are a few places where we can clean up some of our code and make this +look just a bit better. You may have noticed that when we added the `onChange` +handler in the last lesson that we used the exact same code to get a new reading +time that we did in the `componentDidMount` function. Let's just update the +`componentDidMount` function to call this new function that we created to +calculate the reading time: ```es6 - -``` - -We've just updated the textarea to call a `textChanged` function any time the -textarea value changes. Ok, so now we need to implement this function. Let's -add this function at the top of our component: -```es6 -textChanged = () => { - +componentDidMount() { + this.updateReadingTime() } ``` -## Arrow functions - -You may notice some funny looking syntax there. What's with this fat arrow -business `=>`? That's some ES6 syntactical sugar that automatically binds -that function to `this`. In this case `this` is the entire scopr of the -component. We run into trouble with `onChange` handlers like that, because -when the function is fired, it is in the scope of the `textarea` component, -and we need access to the global component scope. By using an arrow function -like that, we will now have access to the component's scope. Great! - -## Making the component update +Refresh your page and make sure it works. And it does! -Ok, so now we've trapped that onChange event, but what do we do with it? We -need to tell the `ReadingTime` component to update the word count when this -happens. But how do we communicate with it? React provides a way to do this -and it's called [refs](https://facebook.github.io/react/docs/more-about-refs.html). -We can add a "reference" to a component, and then access it's internal -methods form the parent component. Let's add a ref to the `ReadingTime` component" +In the last lessong we also added the word `minutes` to our reading time +output. But what about the case where the number is `1`? That's not going to +make much sense. We're going to need a little bit of logic to determine +whether or not to use the pluralized version of minutes or not. Let's add some +logic in the render method to accomplish this. Update your render method to +look like this: ```es6 - -``` +render() { + let props = this.props, + { readTime } = this.state, + minutes = readTime === 1 ? 'minute' : 'minutes' -So now that we have a reference to the component, we can tell it to update: -```es6 -textChanged = () => { - this.refs.readingTime.updateReadingTime() + return ( +
+

+ Estimated read time:

+ {readTime} {minutes} +

+
+ ) } ``` -When you add a ref to a component, that component is then added to a `refs` -array on the parent component. So we can access it through `this.refs` and -then the name of the ref. At this point, we have the instance of the element -and call tell it to do whatever we want! Now we'll need to implement the -`updateReadingTime` function in the `ReadingTime` component. Go ahead and open -that file and let's add it: +Ok so we've introduced a few new concepts that may seem strange here. Let's +start with this strange looking variable assignment: ```es6 -updateReadingTime = () => { - let selector = '[data-article]', - article = document.querySelector(selector), - text = this.getText(article), - wordCount = this.countWords(text), - readTime = Math.round(wordCount / this.props.wordsPerMinute) +{ readTime } = this.state +``` - this.setState({ readTime: readTime }) +This is called `destructuring` and is an ES6 feature that makes assigning +variables super easy. Remember what our state object looks like: +```json +{ + readTime: 1 } ``` -That's all we need to do! Now you be able to happily type away and the widget -will update automatically! Awesome stuff! Of course, because we need to add -270 words to make the reading time increase by 1 minute, it will take quite -a few words to make it update. To make it more responsive go ahead and update -the default `wordsPerMinute` to something much lower (like 1) and watch it -update right away. Just make sure you move it back up to 270. :) +By using the destructuring syntax, you can assign variables to the names of +the keys in the object, and the variable will receive the value of that key. +Pretty neat! Now any time we want to use the variable from the state we can +just type `readTime` instead of `this.state.readTime`. Saves a **lot** of +typing. -Let's update the `ReadingTime` widget to make the output look just a bit nicer: +The next thing we should do is change our variable assignment from a `let` +to a `const`. This just ensures that our variables will not change. Anything +inside the render method should be immutable, so we can convey that message +by changes all the assignments to a `const`: ```es6 -return ( -
-

- Estimated read time:

- {this.state.readTime} minutes -

-
-) +render() { + const props = this.props, + { readTime } = this.state, + minutes = readTime === 1 ? 'minute' : 'minutes' + + return ( +
+

+ Estimated read time:

+ {readTime} {minutes} +

+
+ ) +} ``` -All we did there was just add the word `minutes` at the end of the reading time -count. +That's it for our refactoring! Our little app is looking pretty good! ## Next lesson... -We're almost there! We just need to spend some time cleaning a few things up... +We've got one final lesson, and we're going to fine tune our widget and give +it a few more defaults... From 031b2dc74f992f23dbc96912178ac23bb46f3d00 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sun, 6 Dec 2015 20:37:11 -0800 Subject: [PATCH 24/34] Initial commit for Lesson 4.3 /* # Please enter the commit message for your changes. Lines starting */ /* # with '#' will be ignored, and an empty message aborts the commit. */ /* # On branch lesson4.3 */ /* # Changes to be committed: */ --- readme.md | 115 +++++++++++++++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/readme.md b/readme.md index 664237c..e02a40f 100644 --- a/readme.md +++ b/readme.md @@ -1,75 +1,76 @@ -# Refactoring!! +# Sensible defaults and finishing up!!! -There are a few places where we can clean up some of our code and make this -look just a bit better. You may have noticed that when we added the `onChange` -handler in the last lesson that we used the exact same code to get a new reading -time that we did in the `componentDidMount` function. Let's just update the -`componentDidMount` function to call this new function that we created to -calculate the reading time: +We're almost done creating our widget. We just need to wrap up a few more +things. One thing you may have noticed is that we are using a static selector +to grab the DOM node where the article lives. This works for our use case, but +other users may want to use a different selector. What we'll want to do is +add a prop for this, so that it can be defined. Let's refactor our `ReadingTime` +component to allow this. + +First, we'll add it to the `propTypes`: ```es6 -componentDidMount() { - this.updateReadingTime() +static propTypes = { + wordsPerMinute: React.PropTypes.number, + selector: React.PropTypes.string } ``` -Refresh your page and make sure it works. And it does! +Then we can add it to the `defaultProps`, and we'll use our current selector +as the default: +```es6 +static defaultProps = { + wordsPerMinute: 270, + selector: '[data-article]' +} +``` -In the last lessong we also added the word `minutes` to our reading time -output. But what about the case where the number is `1`? That's not going to -make much sense. We're going to need a little bit of logic to determine -whether or not to use the pluralized version of minutes or not. Let's add some -logic in the render method to accomplish this. Update your render method to -look like this: +Ok, so now we've defined the props. Let's update our code to use these props. +We will only need to update the `updateReadingTime` function to use this +selector, as that's the only place in our component where the selector is used: ```es6 -render() { - let props = this.props, - { readTime } = this.state, - minutes = readTime === 1 ? 'minute' : 'minutes' +updateReadingTime = () => { + let { selector, wordsPerMinute } = this.props, + article = document.querySelector(selector), + text = this.getText(article), + wordCount = this.countWords(text), + readTime = Math.round(wordCount / wordsPerMinute) - return ( -
-

- Estimated read time:

- {readTime} {minutes} -

-
- ) + this.setState({ readTime: readTime }) } ``` -Ok so we've introduced a few new concepts that may seem strange here. Let's -start with this strange looking variable assignment: +Great, now our component is way more flexible, and users can pass in a custom +selector! You may have noticed that I added in a bit of destructuring there +too in order to make accessing our variables easier. Gotta love ES6!! + +Ok, we're are almost there, I just want to add one more piece to make it just +a bit more customizable, and to be able to demonstrate one more neat feature +of destructuring. Let's allow the user to customize the text color inside the +widget. We'll add one more prop to our `propTypes` and `defaultProps`: ```es6 -{ readTime } = this.state -``` +static propTypes = { + wordsPerMinute: React.PropTypes.number, + selector: React.PropTypes.string, + textColor: React.PropTypes.string +} -This is called `destructuring` and is an ES6 feature that makes assigning -variables super easy. Remember what our state object looks like: -```json -{ - readTime: 1 +static defaultProps = { + wordsPerMinute: 1, + selector: '[data-article]', + textColor: 'blue' } ``` -By using the destructuring syntax, you can assign variables to the names of -the keys in the object, and the variable will receive the value of that key. -Pretty neat! Now any time we want to use the variable from the state we can -just type `readTime` instead of `this.state.readTime`. Saves a **lot** of -typing. - -The next thing we should do is change our variable assignment from a `let` -to a `const`. This just ensures that our variables will not change. Anything -inside the render method should be immutable, so we can convey that message -by changes all the assignments to a `const`: +The last thing we need to do is update our render method: ```es6 render() { - const props = this.props, + const { textColor, ...rest } = this.props, { readTime } = this.state, minutes = readTime === 1 ? 'minute' : 'minutes' return ( -
-

+

+

Estimated read time:

{readTime} {minutes}

@@ -78,9 +79,15 @@ render() { } ``` -That's it for our refactoring! Our little app is looking pretty good! +What I've done here is use the power of ES6 destructuring to be able to grab +just the variables I need from the props, and then assign the "rest" of them +to a variable so they can be passed into our components main div. This allows +us to have some static props that we need to use in our component, but still +allow other developers to pass in arbitrary props and they will end up on the +div. Pretty awesome! I also used the `textColor` prop to set the text color +in our widget. -## Next lesson... +That's it! We've finished our whirlwind tour of React, and you should now be +able to go out into the world and write some amazing ReactJS applications! -We've got one final lesson, and we're going to fine tune our widget and give -it a few more defaults... +Congratulations! From 7f803c68bc7db58dcc19363d2540c5aa0f7d03d4 Mon Sep 17 00:00:00 2001 From: Andrew Krespanis Date: Tue, 15 Dec 2015 19:45:52 +1100 Subject: [PATCH 25/34] tech edit --- readme.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index e02a40f..57bddfb 100644 --- a/readme.md +++ b/readme.md @@ -39,13 +39,13 @@ updateReadingTime = () => { } ``` -Great, now our component is way more flexible, and users can pass in a custom +Great, now our component is more flexible, because users can pass in a custom selector! You may have noticed that I added in a bit of destructuring there too in order to make accessing our variables easier. Gotta love ES6!! -Ok, we're are almost there, I just want to add one more piece to make it just +Ok, we're are almost there, I just want to add one more piece to make it a bit more customizable, and to be able to demonstrate one more neat feature -of destructuring. Let's allow the user to customize the text color inside the +of destructuring. Lets allow the user to customize the text color inside the widget. We'll add one more prop to our `propTypes` and `defaultProps`: ```es6 static propTypes = { @@ -61,7 +61,7 @@ static defaultProps = { } ``` -The last thing we need to do is update our render method: +The last thing we need to do is update our `render` method: ```es6 render() { const { textColor, ...rest } = this.props, @@ -81,10 +81,10 @@ render() { What I've done here is use the power of ES6 destructuring to be able to grab just the variables I need from the props, and then assign the "rest" of them -to a variable so they can be passed into our components main div. This allows +to a variable so they can be passed into our component's main `div`. This allows us to have some static props that we need to use in our component, but still allow other developers to pass in arbitrary props and they will end up on the -div. Pretty awesome! I also used the `textColor` prop to set the text color +`div`. Pretty awesome! I also used the `textColor` prop to set the text color in our widget. That's it! We've finished our whirlwind tour of React, and you should now be From a08e8439bc322bdc56bddfe773dbaf85e4242a45 Mon Sep 17 00:00:00 2001 From: Bruno Mota Date: Fri, 22 Jan 2016 12:16:37 +0000 Subject: [PATCH 26/34] to refactor from previous code --- readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 57bddfb..c465564 100644 --- a/readme.md +++ b/readme.md @@ -6,7 +6,7 @@ to grab the DOM node where the article lives. This works for our use case, but other users may want to use a different selector. What we'll want to do is add a prop for this, so that it can be defined. Let's refactor our `ReadingTime` component to allow this. - +[INVALID] First, we'll add it to the `propTypes`: ```es6 static propTypes = { @@ -86,6 +86,7 @@ us to have some static props that we need to use in our component, but still allow other developers to pass in arbitrary props and they will end up on the `div`. Pretty awesome! I also used the `textColor` prop to set the text color in our widget. +[/INVALID] That's it! We've finished our whirlwind tour of React, and you should now be able to go out into the world and write some amazing ReactJS applications! From b712707b639551ffa6332a0f1f497a649fdd668a Mon Sep 17 00:00:00 2001 From: dphaener Date: Sun, 24 Jan 2016 10:27:38 -0800 Subject: [PATCH 27/34] Update to reflect changes --- readme.md | 61 +++++++++++-------------------------------------------- 1 file changed, 12 insertions(+), 49 deletions(-) diff --git a/readme.md b/readme.md index c465564..6206905 100644 --- a/readme.md +++ b/readme.md @@ -1,72 +1,36 @@ # Sensible defaults and finishing up!!! We're almost done creating our widget. We just need to wrap up a few more -things. One thing you may have noticed is that we are using a static selector -to grab the DOM node where the article lives. This works for our use case, but -other users may want to use a different selector. What we'll want to do is -add a prop for this, so that it can be defined. Let's refactor our `ReadingTime` -component to allow this. -[INVALID] -First, we'll add it to the `propTypes`: +things. Lets allow the user to customize the text color inside the +widget. We'll add one more prop to our `propTypes` and `defaultProps`: + ```es6 static propTypes = { wordsPerMinute: React.PropTypes.number, - selector: React.PropTypes.string + textColor: React.PropTypes.string } -``` -Then we can add it to the `defaultProps`, and we'll use our current selector -as the default: -```es6 static defaultProps = { - wordsPerMinute: 270, - selector: '[data-article]' -} -``` - -Ok, so now we've defined the props. Let's update our code to use these props. -We will only need to update the `updateReadingTime` function to use this -selector, as that's the only place in our component where the selector is used: -```es6 -updateReadingTime = () => { - let { selector, wordsPerMinute } = this.props, - article = document.querySelector(selector), - text = this.getText(article), - wordCount = this.countWords(text), - readTime = Math.round(wordCount / wordsPerMinute) - - this.setState({ readTime: readTime }) + wordsPerMinute: 1, + textColor: 'blue' } ``` Great, now our component is more flexible, because users can pass in a custom -selector! You may have noticed that I added in a bit of destructuring there +color! You may have noticed that I added in a bit of destructuring there too in order to make accessing our variables easier. Gotta love ES6!! Ok, we're are almost there, I just want to add one more piece to make it a bit more customizable, and to be able to demonstrate one more neat feature -of destructuring. Lets allow the user to customize the text color inside the -widget. We'll add one more prop to our `propTypes` and `defaultProps`: -```es6 -static propTypes = { - wordsPerMinute: React.PropTypes.number, - selector: React.PropTypes.string, - textColor: React.PropTypes.string -} - -static defaultProps = { - wordsPerMinute: 1, - selector: '[data-article]', - textColor: 'blue' -} -``` +of destructuring. The last thing we need to do is update our `render` method: + ```es6 render() { - const { textColor, ...rest } = this.props, - { readTime } = this.state, - minutes = readTime === 1 ? 'minute' : 'minutes' + const { textColor, ...rest } = this.props; + const { readTime } = this.state; + const minutes = readTime === 1 ? 'minute' : 'minutes'; return (
@@ -86,7 +50,6 @@ us to have some static props that we need to use in our component, but still allow other developers to pass in arbitrary props and they will end up on the `div`. Pretty awesome! I also used the `textColor` prop to set the text color in our widget. -[/INVALID] That's it! We've finished our whirlwind tour of React, and you should now be able to go out into the world and write some amazing ReactJS applications! From 45f8400d9e828607deb866da0daf6bb0f34698a0 Mon Sep 17 00:00:00 2001 From: dphaener Date: Wed, 27 Jan 2016 08:50:01 -0800 Subject: [PATCH 28/34] Update copy --- readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 6206905..c23965a 100644 --- a/readme.md +++ b/readme.md @@ -17,8 +17,7 @@ static defaultProps = { ``` Great, now our component is more flexible, because users can pass in a custom -color! You may have noticed that I added in a bit of destructuring there -too in order to make accessing our variables easier. Gotta love ES6!! +color! Ok, we're are almost there, I just want to add one more piece to make it a bit more customizable, and to be able to demonstrate one more neat feature From c281dd1b9790018f8cea8fa38d046f5b6ae734cd Mon Sep 17 00:00:00 2001 From: dphaener Date: Wed, 27 Jan 2016 09:05:10 -0800 Subject: [PATCH 29/34] Add lesson5.1 content --- readme.md | 69 +++++++++++++++---------------------------------------- 1 file changed, 19 insertions(+), 50 deletions(-) diff --git a/readme.md b/readme.md index c23965a..3f67867 100644 --- a/readme.md +++ b/readme.md @@ -1,56 +1,25 @@ -# Sensible defaults and finishing up!!! +# Course Conclusion -We're almost done creating our widget. We just need to wrap up a few more -things. Lets allow the user to customize the text color inside the -widget. We'll add one more prop to our `propTypes` and `defaultProps`: +Congratulations! You've finished the ReactJS the ES6 way course! -```es6 -static propTypes = { - wordsPerMinute: React.PropTypes.number, - textColor: React.PropTypes.string -} +You're now ready to take on the world and start writing declarative, +composable ReactJS applications using all of the great new ES6 features. -static defaultProps = { - wordsPerMinute: 1, - textColor: 'blue' -} -``` + * We installed Node and NPM + * We learned how to setup a basic Webpack configuration + * We learned how to setup and start a Webpack development server + * We learned about quite a few new ES6 operators and shortcuts like + destructuring, spread operators, and static constructors. + * We then learned how to create React components using ES6 classes, and + how to use props and state. + * We learned how React uses the Virtual DOM to make webpages dynamic and + incredibly fast. -Great, now our component is more flexible, because users can pass in a custom -color! +This was a great introduction, but now it's time to get out there and learn +even more about React. I would suggest you look into the following topics to +further increase your knowledge of React: -Ok, we're are almost there, I just want to add one more piece to make it -a bit more customizable, and to be able to demonstrate one more neat feature -of destructuring. + * The Flux architecture + * Implementations of Flux like Alt and Redux + * The Relay framework for declarative data fetching -The last thing we need to do is update our `render` method: - -```es6 -render() { - const { textColor, ...rest } = this.props; - const { readTime } = this.state; - const minutes = readTime === 1 ? 'minute' : 'minutes'; - - return ( -
-

- Estimated read time:

- {readTime} {minutes} -

-
- ) -} -``` - -What I've done here is use the power of ES6 destructuring to be able to grab -just the variables I need from the props, and then assign the "rest" of them -to a variable so they can be passed into our component's main `div`. This allows -us to have some static props that we need to use in our component, but still -allow other developers to pass in arbitrary props and they will end up on the -`div`. Pretty awesome! I also used the `textColor` prop to set the text color -in our widget. - -That's it! We've finished our whirlwind tour of React, and you should now be -able to go out into the world and write some amazing ReactJS applications! - -Congratulations! From 36fe1445124ae67ce25505b4b4d0fb0feb15d608 Mon Sep 17 00:00:00 2001 From: dphaener Date: Wed, 27 Jan 2016 09:16:40 -0800 Subject: [PATCH 30/34] Add more copy. --- readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.md b/readme.md index 3f67867..b35f9e1 100644 --- a/readme.md +++ b/readme.md @@ -23,3 +23,6 @@ further increase your knowledge of React: * Implementations of Flux like Alt and Redux * The Relay framework for declarative data fetching +I've added a few links in the resources section below that will help you +continue learning. Thanks for taking this journey with me, and have fun creating +application using ReactJS! From 6f6a6a9d8a8891b6d9b0e283cc2b9e6d7536d005 Mon Sep 17 00:00:00 2001 From: dphaener Date: Thu, 28 Jan 2016 22:31:39 -0800 Subject: [PATCH 31/34] lesson 1 final code --- .babelrc | 3 +++ .gitignore | 1 + example/index.html | 12 ++++++++++++ example/webpack.config.js | 32 ++++++++++++++++++++++++++++++++ package.json | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 .babelrc create mode 100644 .gitignore create mode 100644 example/index.html create mode 100644 example/webpack.config.js create mode 100644 package.json diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..ea288b7 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + presets: ['es2015', 'react', 'stage-0'] +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/example/index.html b/example/index.html new file mode 100644 index 0000000..036496a --- /dev/null +++ b/example/index.html @@ -0,0 +1,12 @@ + + + React Reading Time Example + + + +
+
+
+ + + diff --git a/example/webpack.config.js b/example/webpack.config.js new file mode 100644 index 0000000..640c4f8 --- /dev/null +++ b/example/webpack.config.js @@ -0,0 +1,32 @@ +var webpack = require('webpack'); + +module.exports = { + entry: { + 'react-reading-time': [ + 'webpack-dev-server/client?http://localhost:8881/', + 'webpack/hot/only-dev-server', + './example/react-reading-time.jsx' + ] + }, + output: { + path: __dirname, + filename: "[name].js", + publicPath: 'http://localhost:8881/', + chunkFilename: '[id].chunk.js', + sourceMapFilename: '[name].map' + }, + resolve: { + extensions: ['', '.js', '.jsx', '.es6'], + modulesDirectories: ['node_modules'] + }, + module: { + loaders: [ + { test: /\.jsx$|\.es6$|\.js$/, loaders: ['react-hot', 'babel-loader'], exclude: /node_modules/ }, + { test: /\.scss$|\.css$/, loader: 'style-loader!style!css!sass' } + ] + }, + plugins: [ + new webpack.NoErrorsPlugin() + ], + devtool: "eval-source-map" +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..6332014 --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "ReactJS-the-ES6-Way", + "version": "1.0.0", + "description": "Congratulations! You've finished the ReactJS the ES6 way course!", + "main": "index.js", + "scripts": { + "start": "webpack-dev-server --config ./example/webpack.config.js --hot --port 8881" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/learnable-content/ReactJS-the-ES6-Way.git" + }, + "keywords": [], + "author": "Darin Haener (https://github.com/dphaener)", + "license": "ISC", + "bugs": { + "url": "https://github.com/learnable-content/ReactJS-the-ES6-Way/issues" + }, + "homepage": "https://github.com/learnable-content/ReactJS-the-ES6-Way#readme", + "devDependencies": { + "babel": "^6.3.26", + "babel-core": "^6.4.5", + "babel-loader": "^6.2.1", + "babel-preset-es2015": "^6.3.13", + "babel-preset-react": "^6.3.13", + "babel-preset-stage-0": "^6.3.13", + "react": "^0.14.7", + "react-dom": "^0.14.7", + "react-hot-loader": "^1.3.0", + "webpack": "^1.12.12", + "webpack-dev-server": "^1.14.1" + } +} From 214e332de59a30b54b019842521cd124b5cdc561 Mon Sep 17 00:00:00 2001 From: dphaener Date: Thu, 28 Jan 2016 22:35:14 -0800 Subject: [PATCH 32/34] lesson 2 final code --- example/react-reading-time.jsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 example/react-reading-time.jsx diff --git a/example/react-reading-time.jsx b/example/react-reading-time.jsx new file mode 100644 index 0000000..a45b315 --- /dev/null +++ b/example/react-reading-time.jsx @@ -0,0 +1,14 @@ +import React from 'react' +import ReactDOM from 'react-dom' + +class ReactReadingTime extends React.Component { + render() { + return ( +
+ Hello React! +
+ ); + } +} + +ReactDOM.render(, document.getElementById('react')); From ecb7b73cb93d82d373f53f6b61a1ec7b0c7e2801 Mon Sep 17 00:00:00 2001 From: dphaener Date: Thu, 28 Jan 2016 22:43:11 -0800 Subject: [PATCH 33/34] lesson 3 final code --- example/react-reading-time.jsx | 25 +++++++++++++++-- src/reading-time.jsx | 49 ++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 src/reading-time.jsx diff --git a/example/react-reading-time.jsx b/example/react-reading-time.jsx index a45b315..edde9c6 100644 --- a/example/react-reading-time.jsx +++ b/example/react-reading-time.jsx @@ -1,11 +1,32 @@ import React from 'react' import ReactDOM from 'react-dom' +import ReadingTime from '../src/reading-time' class ReactReadingTime extends React.Component { + constructor(props) { + super(props) + + this.state = { + text: 'Foo is baz and bar' + } + } + + updateText(ev) { + this.setState({ text: ev.target.value }) + } + render() { return ( -
- Hello React! +
+
+ +
+
); } diff --git a/src/reading-time.jsx b/src/reading-time.jsx new file mode 100644 index 0000000..6897985 --- /dev/null +++ b/src/reading-time.jsx @@ -0,0 +1,49 @@ +import React from 'react' + +export default class ReadingTime extends React.Component { + static propTypes = { + wordsPerMinute: React.PropTypes.number + }; + + static defaultProps = { + wordsPerMinute: 270 + }; + + constructor(props) { + super(props) + + this.state = { + readTime: 0 + } + } + + componentWillMount() { + this.updateReadingTime(this.props); + } + + componentWillReceiveProps(nextProps) { + this.updateReadingTime(nextProps); + } + + updateReadingTime(props) { + const words = this.countWords(props.text); + const readTime = Math.round(words / props.wordsPerMinute); + + this.setState({ readTime }); + } + + countWords(text) { + return text.split(/\s+/).length + } + + render() { + return ( +
+

+ Estimated read time:

+ {this.state.readTime} +

+
+ ) + } +} From f988742d24117bb97146faa58c625bdbcdd5448c Mon Sep 17 00:00:00 2001 From: spxds Date: Sun, 7 Feb 2016 20:21:19 -0500 Subject: [PATCH 34/34] Update readme.md --- readme.md | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/readme.md b/readme.md index b35f9e1..0668075 100644 --- a/readme.md +++ b/readme.md @@ -1,28 +1 @@ -# Course Conclusion - -Congratulations! You've finished the ReactJS the ES6 way course! - -You're now ready to take on the world and start writing declarative, -composable ReactJS applications using all of the great new ES6 features. - - * We installed Node and NPM - * We learned how to setup a basic Webpack configuration - * We learned how to setup and start a Webpack development server - * We learned about quite a few new ES6 operators and shortcuts like - destructuring, spread operators, and static constructors. - * We then learned how to create React components using ES6 classes, and - how to use props and state. - * We learned how React uses the Virtual DOM to make webpages dynamic and - incredibly fast. - -This was a great introduction, but now it's time to get out there and learn -even more about React. I would suggest you look into the following topics to -further increase your knowledge of React: - - * The Flux architecture - * Implementations of Flux like Alt and Redux - * The Relay framework for declarative data fetching - -I've added a few links in the resources section below that will help you -continue learning. Thanks for taking this journey with me, and have fun creating -application using ReactJS! +# ReactJS the ES6 way