diff --git a/chap02.md b/chap02.md index 758c243..e5ec9a7 100644 --- a/chap02.md +++ b/chap02.md @@ -168,7 +168,7 @@ console.log(lordify("Kelly", "Sonoma")); #### Returning objects -If we want to specify that we want to return an object, wrap the returned object with `()` +If we want to specify that we want to return an object, wrap the returned object with `()`. Otherwise, we will see error `Uncaught SyntaxError: Unexpected token` ```js const person = (firstName, lastName) => { diff --git a/chap03.md b/chap03.md new file mode 100644 index 0000000..4b9ec41 --- /dev/null +++ b/chap03.md @@ -0,0 +1,306 @@ +# Chapter 3. Functional Programming with JavaScript + +## 3.1 What It Means to Be Functional + +JS functions are 1st-class citizens (i.e. functions can be treated as data. It can be saved, retrieved or flow through app), which means it: +* You can declare functions with `var`, `let`, `const` keywords +* Add functions to objects +* Add functions to arrays +* Parsed as argument to other functions +* Returned from other functions +* Used as Higher-Order functions + +### Declare functions with `var`, `let`, `const` + +```js +// declare using traditional function +var log = funciton(message) { + console.log(message); +}; + +// declare using arrow function +const log = message => { + console.log(message); +}; +``` + +### Add functions to objects: + +```js +const obj = { // Prevent it to be overwritten + message: "Functions can be added to objects like variables", + log(message) { // Function is stored in a variable called log + console.log(message); + } +}; + +obj.log(obj.message); +``` + +### Add functions to arrays in JS + +```js +const message = [ + "Functions can be inserted into arrays", + message => console.log(message), + "like variables", + message => console.log(message) +]; + +// Use functions in array +messages[1](messages[0]); // Functions can be inserted into arrays +messages[3](messages[2]); // Like variables +``` + +### Send function as argument to other functions + +```js +const insideFn = logger => { + logger("Function can be sent to other functions as arguments"); +}; + +insideFn(message => console.log(message)); // an arrow function is parsed as argument +``` + +### Return function from another function + +```js +const createScream = function(logger) { + return function(message) { + logger(message.toUpperCase() + "!!!"); + }; // Return a function +}; + +const scream = createScream(message => console.log(message)); // Constructed a console log method + +scream("function can be returned from other functions"); // FUNCTIONS CAN BE RETURNED FROM OTHER FUNCTIONS!!! +``` + +Parse/Return argument into/from another argument are feature of **higher-order function** (i.e. function that either take or return other functions). + +### Higher-Order functions as arrow function + +```js +const createScream = logger => message => { + logger(message.toUpperCase() + "!!!"); +} +``` +* Function declaration with more than one arrow means it's a higher-order function. + + +## 3.2 Imperative Versus Declarative + +* **Declarative programming**: style of (functional) programming where app are structured in a way that prioritizes describing *what* should happen over defining *how* it should happen. +* **Imperitive programming**: style of programming that's only concerned with how to achieve results with codes. + +## 3.3 Functional Concepts + +### 3.3.1 Immutability + +In functional program, data is immutable. Instead of changing original data structures, we build changed copies of those data structures and use them. +* In JS, function arguments are references to actural data. +* To create copy, we can use `Object.assign`. +* To add object to array, use `Array.concat` instead of `Array.push` + +#### Use `Object.assign` or equivalent arrow function to copy and change content + +Given a color object +```js +let color_lawn = { + title: "lawn", + color: "#00FF00", + rating: 0 +}; +``` + +Create a function to rate color +```js +function rateColor(color, rating) { + color.rating = rating; + return color; +} + +console.log(rateColor(color_lawn, 5).rating); // 5 +console.log(color_lawn.rating); // 5 (color_lawn was parsed into argument as reference, change is reflected) +``` + +Rewrite the function, so parsed argument is immutable +```js +const rateColor = function(color, rating) { + return Object.assign({}, color, {rating: rating}); // rating is overwritten +}; + +console.log(rateColor(color_lawn, 5).rating); // 5 +console.log(color_lawn.rating); // 0 +``` + +The function can be further simplified using arrow funciton + +```js +const rateColor = (color, rating) => ( + { + ...color, + rating + } +) +``` +* This function is exactly the same as `Object.assign` + +#### Use `Array.concat` or equivalent spread operator to keep array immutable + +```js +let list = [{ title: "Rad Red" }, { title: "Lawn" }, { title: "Party Pink" }]; +``` + +Add colors to array using `Array.push`, which will change original data + +```js +const addColor = function(title, colors) { + colors.push({ title: title }); + return colors; +}; + +console.log(addColor("Glam Green", list).length); // 4 +console.log(list.length); // 4 +``` + +Use `Array.concat` to keep original data immutable + +```js +const addColor = (title, array) => array.concat({ title }); + +console.log(addColor("Glam Green", list).length); // 4 +console.log(list.length); // 3 +``` + +Use equivalent spread operator + +```js +const addColor = (title, list) => [...list, { title }]; // This will change or add new object +``` + +### 3.3.2 Pure Functions + +**Pure function** = a function that returns a value that computed based on its arguments. +* Rules of pure function: + * Pure function takes arguments (treat as immutable data) and return a value or another function based on given arguments + * Pure function do not + * cause side effects + * set global variables + * Change any app states. +* Benefit of pure function: + * Pure functions are **testable**, as they do not change anything outside of its scope. UT on pure functions do not require complicated test setups. + +e.g. Impure function + +```js +const frederick = { + name: "Frederick Douglass", + canRead: false, + canWrite: false +}; + +function selfEducate() { + frederick.canRead = true; + frederick.canWrite = true; + return frederick; +} + +selfEducate(); +console.log(frederick); +// {name: "Frederick Douglass", canRead: true, canWrite: true} +``` +Problem of impure function `selfEducate`: +* It do not take any arguments, +* It do not return a vlue or a function. +* It changes a variable outside of its scope: `Frederick`. + +Change to pure function +```js +const selfEducate = person => ({ + ...person, + canRead: true, + canWrite: true +}); + +console.log(selfEducate(frederick)); +console.log(frederick); + +// {name: "Frederick Douglass", canRead: true, canWrite: true} +// {name: "Frederick Douglass", canRead: false, canWrite: false} +``` + +#### Summary of Pure function + +Pure function is an important core concept of function programming. It make development easier as it does not change application's state. Three rules to follow, when writing functions: +1. The function should take in at least 1 argument. +2. The function should return a value or another function. +3. The function should not change or mutate any of its argument. + +### 3.3.3 Data Transformations + +Functional JS has tools for data transformation without altering the original. Two core functions are: +* `Array.map` +* `Array.reduce` + +#### `Array.join` to combine array + +```js +const schools = ["Yorktown", "Washington & Liberty", "Wakefield"]; +console.log(schools.join(", ")); // "Yorktown, Washington & Liberty, Wakefield" +console.log(schools); // (3) ['Yorktown', 'Washington & Liberty', 'Wakefield'] +``` +* Original array is not changed. + +#### `Array.filter` to monidfy array while maintain immutability + +`Array.filter` takes a predicate (谓词) as its only argument, and return an array consisting items that fit the prediate criteria +* A predicate is a function that return a Boolean value: `true` or `false`. +* `Array.filter` invokes this predicate for every item in array (like for loop). + * Each item is passed to predicate as an argument + * The return value (`true` or `false`) is used to decide if the item will be added to new array. + +```js +const wSchools = schools.filter(school => school[0] === "W"); +console.log(wSchools); // ["Washington & Liberty", "Wakefield"] +``` + +```js +const cutSchool = (cut, list) => list.filter(x => x != cut); +console.log(cutSchool("Washington & Liberty", schools).join(", ")); // "Yorktown, Wakefield" +``` + +Benefit of `Array.filter`: +* good for removing an item from an array; better than `Array.pop` or `Array.splice`, as `Array.filter` is immutable + +#### `Array.map` to produce mutated array + +`Array.map` method takes a function as its argument, and return mutated items in new array: +* The function will be invoked once for every item in the array, and whatever it returns will be added to new array + +```js +const highSchools = schools.map(school => `${school} High School`); // append "High School" to each item +console.log(highSchools.join("\n")); +// Yorktown High School +// Washington & Liberty High School +// Wakefield High School +``` + +e.g. Use `.map` to transfer array of strings to array of objects +```js +const highSchools = schools.map(school => ({ name: school})); +console.log(highSchools); +// [ +// { name: "Yorktown" }, +// { name: "Washington & Liberty" }, +// { name: "Wakefield" } +// ] +``` + +### 3.3.4 Higher-Order Functions + +### 3.3.5 Recursion + +### 3.3.6 Composition + +### 3.3.7 Putting It All Together \ No newline at end of file diff --git a/chap04.md b/chap04.md new file mode 100644 index 0000000..101c23b --- /dev/null +++ b/chap04.md @@ -0,0 +1,13 @@ +# Chapter 4. How React Works + +## 4.1 Page Setup + +## 4.2 React Elements + +## 4.3 React DOM + +### 4.3.1 Children + +## 4.4 React Components + +### 4.4.1 React Componenets: A Historical Tour \ No newline at end of file diff --git a/chap05.md b/chap05.md new file mode 100644 index 0000000..9287464 --- /dev/null +++ b/chap05.md @@ -0,0 +1,15 @@ +# Chapter 5. React with JSX + +## 5.1 React Elements as JSX + +### 5.1.2 JSX Tips + +### 5.1.3 Mapping Arrays with JSX + +## 5.2 Babel + +## 5.3 Recipes as JSX + +## 5.4 React Fragments + +## 5.5 Intro to webpack \ No newline at end of file diff --git a/chap06.md b/chap06.md new file mode 100644 index 0000000..e321e8a --- /dev/null +++ b/chap06.md @@ -0,0 +1,33 @@ +# Chapter 6. React State Management + +## 6.1 Building a Star Rating Component + +## 6.2 The useState Hook + +## 6.3 Refactoring for Advanced Reusability + +## 6.4 State in Component Trees + +### 6.4.1 Sending State Down a Component Tree + +### 6.4.2 Sending Interations Back up a Component Tree + +## 6.5 Building Forms + +### 6.5.1 Using Refs + +### 6.5.2 Controlled Components + +### 6.5.3 Creating Custom Hooks + +### 6.5.4 Adding Colors to State + +## 6.6 React Context + +### 6.6.1 Placing Colors in Context + +### 6.6.2 Retrieving Colors with useContext + +### 6.6.3 Stateful Context Providers + +### 6.6.4 Custom Hooks with Context \ No newline at end of file