4,452
edits
add personal blogs to references |
|||
(15 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
Notes from Learning React, 2nd Edition by Porcello & Banks | Notes from '''Learning React, 2nd Edition''' by Porcello & Banks and other sources | ||
= Installation = | = Installation = | ||
Line 86: | Line 86: | ||
== Arrow functions and scope == | == Arrow functions and scope == | ||
Reference | |||
* [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions Arrow functions] | |||
* [https://www.codementor.io/dariogarciamoya/understanding-this-in-javascript-with-arrow-functions-gcpjwfyuc Understanding "this" in javascript with arrow functions] | |||
<source lang="js"> | <source lang="js"> | ||
Line 116: | Line 123: | ||
tahoe.print(); // Freel, Rose, Tallac, Rubicon, Silver | tahoe.print(); // Freel, Rose, Tallac, Rubicon, Silver | ||
</source> | </source> | ||
== Destructing objects == | == Destructing objects == | ||
Line 259: | Line 265: | ||
== Spread operator == | == Spread operator == | ||
Reference: [https://github.com/tc39/proposal-object-rest-spread Object Rest/Spread Properties for ECMAScript] | |||
<source lang="js"> | <source lang="js"> | ||
Line 327: | Line 335: | ||
// } | // } | ||
</source> | </source> | ||
== Asynchronous requests == | == Asynchronous requests == | ||
Line 1,366: | Line 1,373: | ||
startTicking(); | startTicking(); | ||
</source> | </source> | ||
= How React Works = | |||
== React elements == | |||
<source lang="js"> | |||
React.createElement("h1", { id: "recipe-0" }, "Baked Salmon"); | |||
// <h1 id="recipe-0">Baked Salmon</h1> | |||
// log: | |||
{ | |||
$$typeof: Symbol(React.element), | |||
"type": "h1", | |||
"key": null, | |||
"ref": null, | |||
"props": {id: "recipe-0", children: "Baked Salmon"}, | |||
"_owner": null, | |||
"_store": {} | |||
} | |||
</source> | |||
== ReactDOM == | |||
contains tools necessary to render React element in the browser via '''render''' method | |||
<source lang="js"> | |||
const dish = React.createElement("h1", null, "Baked Salmon"); | |||
ReactDOM.render(dish, document.getElementById("root")); | |||
</source> | |||
rendering array of elements | |||
<source lang="js"> | |||
const dish = React.createElement("h1", null, "Baked Salmon"); | |||
const dessert = React.createElement("h2", null, "Coconut Cream Pie"); | |||
ReactDOM.render([dish, dessert], document.getElementById("root")); | |||
</source> | |||
== Children == | |||
<source lang="js"> | |||
React.createElement( | |||
"ul", | |||
null, | |||
React.createElement("li", null, "2 lb salmon"), | |||
React.createElement("li", null, "5 sprigs fresh rosemary"), | |||
React.createElement("li", null, "2 tablespoons olive oil"), | |||
React.createElement("li", null, "2 small lemons"), | |||
React.createElement("li", null, "1 teaspoon kosher salt"), | |||
React.createElement("li", null, "4 cloves of chopped garlic") | |||
); | |||
// equivalent to | |||
const items = [ | |||
"2 lb salmon", | |||
"5 sprigs fresh rosemary", | |||
"2 tablespoons olive oil", | |||
"2 small lemons", | |||
"1 teaspoon kosher salt", | |||
"4 cloves of chopped garlic" | |||
]; | |||
React.createElement( | |||
"ul", | |||
{ className: "ingredients" }, | |||
items.map((ingredient, i) => React.createElement("li", { key: i }, ingredient)) | |||
); | |||
</source> | |||
== React Components == | |||
<source lang="js"> | |||
function IngredientsList({ items }) { // destructure items from props | |||
return React.createElement( | |||
"ul", | |||
{ className: "ingredients" }, | |||
items.map((ingredient, i) => React.createElement("li", { key: i }, ingredient) | |||
); | |||
} | |||
const items = [ | |||
"2 lb salmon", | |||
"5 sprigs fresh rosemary", | |||
"2 tablespoons olive oil", | |||
"2 small lemons", | |||
"1 teaspoon kosher salt", | |||
"4 cloves of chopped garlic" | |||
]; | |||
ReactDOM.render( | |||
React.createElement(IngredientsList, { items }, null), | |||
document.getElementById("root") | |||
); | |||
</source> | |||
use functions to create components because class syntax is being deprecated. | |||
= React with JSX = | |||
== React elements as JSX == | |||
=== Nested components === | |||
<source lang="html"> | |||
<IngredientsList> | |||
<Ingredient /> | |||
<Ingredient /> | |||
<Ingredient /> | |||
</IngredientsList> | |||
</source> | |||
=== ClassName === | |||
Since <code>class</code> is a reserved word in JavaScript, className is used to define the class attribute. | |||
=== JavaScript Expressions === | |||
<source lang="js"> | |||
<h1>{title}</h1> | |||
<input type="checkbox" defaultChecked="{false}" /> | |||
</source> | |||
=== Evaluation === | |||
<source lang="js"> | |||
<h1>{"Hello" + title}</h1> | |||
<h1>{title.toLowerCase().replace}</h1> | |||
function appendTitle({ title }) { | |||
console.log(`${title} is great!`); | |||
} | |||
</source> | |||
=== Mapping Arrays with JSX === | |||
<source lang="js"> | |||
<ul> | |||
{props.ingredients.map((ingredient, i) => ( | |||
<li key="{i}">{ingredient}</li> | |||
))} | |||
</ul> | |||
</source> | |||
== Babel == | |||
template file to use | |||
<source lang="html"> | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<meta charset="utf-8" /> | |||
<title>React Examples</title> | |||
</head> | |||
<body> | |||
<div id="root"></div> | |||
<!-- React Library & React DOM --> | |||
<script src="https://unpkg.com/react@16.8.6/umd/react.development.js"></script> | |||
<script src="https://unpkg.com/react-dom@16.8.6/umd/react-dom.development.js"></script> | |||
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> | |||
<script type="text/babel"> | |||
// JSX code here. Or link to separate JavaScript file that contains JSX. | |||
</script> | |||
</body> | |||
</html> | |||
</source> | |||
== Recipes as JSX == | |||
<source lang="js"> | |||
const data = [ | |||
{ | |||
name: "Baked Salmon", | |||
ingredients: [ | |||
{ name: "Salmon", amount: 1, measurement: "l lb" }, | |||
{ name: "Pine Nuts", amount: 1, measurement: "cup" }, | |||
{ name: "Butter Lettuce", amount: 2, measurement: "cups" }, | |||
{ name: "Yellow Squash", amount: 1, measurement: "med" }, | |||
{ name: "Olive Oil", amount: 0.5, measurement: "cup" }, | |||
{ name: "Garlic", amount: 3, measurement: "cloves" } | |||
], | |||
steps: [ | |||
"Preheat the oven to 350 degrees.", | |||
"Spread the olive oil around a glass baking dish.", | |||
"Add the yellow squash and place in the oven for 30 mins.", | |||
"Add the salmon, garlic, and pine nuts to the dish.", | |||
"Bake for 15 minutes.", | |||
"Remove from oven. Add the lettuce and serve." | |||
] | |||
}, | |||
{ | |||
name: "Fish Tacos", | |||
ingredients: [ | |||
{ name: "Whitefish", amount: 1, measurement: "l lb" }, | |||
{ name: "Cheese", amount: 1, measurement: "cup" }, | |||
{ name: "Iceberg Lettuce", amount: 2, measurement: "cups" }, | |||
{ name: "Tomatoes", amount: 2, measurement: "large" }, | |||
{ name: "Tortillas", amount: 3, measurement: "med" } | |||
], | |||
steps: [ | |||
"Cook the fish on the grill until cooked through.", | |||
"Place the fish on the 3 tortillas.", | |||
"Top them with lettuce, tomatoes, and cheese." | |||
] | |||
} | |||
]; | |||
// A function component for an individual Recipe | |||
function Recipe (props) { | |||
... | |||
} | |||
// A function component for the Menu of Recipes | |||
function Menu (props) { | |||
return ( | |||
<article> | |||
<header> | |||
<h1>{props.title}</h1> | |||
</header> | |||
<div className="recipes"> | |||
{props.recipes.map((recipe, i) => ( | |||
<Recipe | |||
key={i} | |||
name={recipe.name} | |||
ingredients={recipe.ingredients} | |||
steps={recipe.steps} | |||
/> | |||
))} | |||
// equivalent to | |||
{ | |||
props.recipes.map((recipe, i) => <Recipe key={i} {...recipe} />); | |||
} | |||
</div> | |||
</article> | |||
); | |||
} | |||
// A call to ReactDOM.render to render our Menu into the current DOM | |||
ReactDOM.render( | |||
<Menu recipes={data} title="Delicious Recipes" />, | |||
document.getElementById("root") | |||
); | |||
</source> | |||
we can access title & recipes vars directly, so vars don't have to be prefixed with props: | |||
<source lang="js"> | |||
function Menu({ title, recipes }) { | |||
return ( | |||
<article> | |||
<header> | |||
<h1>{title}</h1> | |||
</header> | |||
<div className="recipes"> | |||
{recipes.map((recipe, i) => ( | |||
<Recipe key={i} {...recipe} /> | |||
))} | |||
</div> | |||
</article> | |||
); | |||
} | |||
</source> | |||
code for the component for each individual recipe: | |||
<source lang="js"> | |||
function Recipe({ name, ingredients, steps }) { | |||
return ( | |||
<section id={name.toLowerCase().replace(/ /g, "-")}> | |||
<h1>{name}</h1> | |||
<ul className="ingredients"> | |||
{ingredients.map((ingredient, i) => ( | |||
<li key={i}>{ingredient.name}</li> | |||
))} | |||
</ul> | |||
<section className="instructions"> | |||
<h2>Cooking Instructions</h2> | |||
{steps.map((step, i) => ( | |||
<p key={i}>{step}</p> | |||
))} | |||
</section> | |||
</section> | |||
); | |||
} | |||
</source> | |||
== React fragments == | |||
<source lang="js"> | |||
function Cat({ name }) { | |||
return ( | |||
<React.Fragment> | |||
<h1>The cat's name is {name}</h1> | |||
<p>He's good.</p> | |||
</React.Fragment> | |||
); | |||
} | |||
// equivalent to | |||
function Cat({ name }) { | |||
return ( | |||
<> | |||
<h1>The cat's name is {name}</h1> | |||
<p>He's good.</p> | |||
</> | |||
); | |||
} | |||
</source> | |||
== Intro to webpack == | |||
* Code splitting | |||
* Minification | |||
* Feature flagging | |||
* Hot module replacement (HMR) | |||
* Modularity | |||
* Composition | |||
* Speed | |||
* Consistency | |||
Installing webpack | |||
<source lang="console"> | |||
$ npm install --save-dev webpack@next webpack-cli | |||
</source> | |||
Installing Babel dependencies | |||
<source lang="console"> | |||
$ npm install babel-loader @babel/core --save-dev | |||
</source> | |||
Specify Babel presets | |||
<source lang="console"> | |||
$ npm install @babel/preset-env @babel/preset-react --save-dev | |||
</source> | |||
= React State Management = | |||
= Reference = | |||
* [https://react-icons.netlify.com React Icons] | |||
* Personal blogs | |||
** [https://www.leighhalliday.com Leigh Halliday] | |||
** [https://www.robinwieruch.de Robin Wieruch] |