# React notes :::info :bulb: Hello all, this is an informal learning space for React. The learning materials come from codecademy, which is a great learning source, and I welcome everyone to pick up programming skills on it! ::: ## Objects, components, elements, attributes ``` const owl = { title: 'Excellent Owl', src: 'https://content.codecademy.com/courses/React/react_photo-owl.jpg' }; //Define function component here: function Owl(){ return ( <div> <h1> {owl.title} </h1> <img src={owl.src} alt={owl.title} /> </div> ); } ``` * owl = {} || owl is OBJECT * title : '' || title is PROPERTY * function Owl(){} || Owl() is COMPONENT * < img />> || img is ELEMENT * < img scr={} /> || src is ATTRIBUTE ## Object destructuring purpose: assign value to a variable withouth deuplicating the property name. ``` const hero = { name: 'Batman', realName: 'Bruce Wayne' }; const { name, realName } = hero; console.log(name); // => 'Batman', console.log(realName); // => 'Bruce Wayne' ``` 使用object destructuring之後: ``` const name = hero.name; const realName = hero.realName; // is equivalent to: const { name, realName } = hero; ``` ### multiple properties `const { prop1, prop2, ..., propN} = object;` ### default value `const {prop = 'default'} = objectt;` ### Alias create variables of different names `const { prop: myProp} =object;` e.g.,以下是Alias舉例 ``` const hero = { name: 'Batman', realName: 'Bruce Wayne' }; const { realName: secretName } = hero; console.log(secretName); // => 'Bruce Wayne' ``` ### Dynamic property name `const{[propName]: myProp } = object;` source: [how to object destructuring in JS](https://dmitripavlutin.com/javascript-object-destructuring/) ## React Component :::success **Create an Button** Give this <button> element an onClick attribute. The attribute’s value should be the handleClick function. source: [Event Listener and Event Handlers in a Component](https://www.codecademy.com/courses/learn-react-introduction/lessons/react-components-advanced-jsx/exercises/component-event-listener) ::: <!-- --> In Button.js, ``` import React from 'react'; function SubmitButton() { function handleClick() { alert('Submission Successful.'); } return <button onClick ={handleClick}>Submit</button>; } export default SubmitButton; ```` In App.js, ``` import React from 'react'; import ReactDOM from 'react-dom'; import Button from './Button' function App() { return <Button />; } export default App; ``` In index.js, ``` import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; ReactDOM.createRoot( document.getElementById('app') ).render(<App />); ``` :question: why " document.getElementById('app')" instead of document.getElementById('App')? <!-- end the list --> ## :star: Functions and Arrow :::success source: [functions-review](https://www.codecademy.com/courses/introduction-to-javascript/lessons/functions/exercises/review-functions) ::: A function is a **reusable block** of code that groups together a sequence of statements to perform **a specific task**. A function declaration: function helloWorld(){ console.log("HelloWorld"); } A parameter is a named variable inside a function's block. function salary(monthlyPay, year){ console.log(monthlyPay*year); } You can set a default value in a parameter. ``` function salary(monthlyPay, year=12){ return monthlyPay*year; } let total = salary(3000); console.log(total); // output: 36000 ``` Set a function expression: ``` const salary = function totalSalary(monthlyPay, year){ return monthlyPay*year } let total = salary(3000,30); console.log(total); //output = 90000 ``` Use arrow function notation: ``` const salary = (monthlyPay, year) => { return monthlyPay*year; } ``` or simplify to this: const salary = (monthlyPay, year) => montlyPay*year; ## Arrow Function and this :::success source: [The this Keyword](https://www.codecademy.com/courses/introduction-to-javascript/lessons/advanced-objects/exercises/adv-this) ::: ``` const robot = { model : '1E78V2', energyLevel : 100, provideInfo : () => `I am ${this.model} and my current energy level is ${robot.energyLevel}.`, } }; console.log(robot.provideInfo()); //output 'I am undefined and my current energy level is 100.' ``` :star: avoid using arrow functions when using this in a method. Instead, the code should be adjusted like this: ``` const robot = { provideInfo() { return `I am ${this.model}.` } }; ``` ## Variable Attribute in a Component :::success source: [Use a Variable Attribute in a Component](https://www.codecademy.com/courses/learn-react-introduction/lessons/react-components-advanced-jsx/exercises/component-variable-attribute) ::: ``` import React from 'react'; const owl = { title: 'Excellent Owl', src: 'https://content.codecademy.com/courses/React/react_photo-owl.jpg' }; function Owl(){ return ( <div> <h1> {owl.title} </h1> <img src={owl.src} alt={owl.title} /> </div> ); } ``` export default Owl; :star: return()內如果有多個elements, 要用 < div >< /div >包裝,才取得到完整render項目。 ## props :::success Every component has something called props. A component’s props is an object. It holds information about that component. source: [Pass `props` to a Component](https://www.codecademy.com/courses/learn-react-introduction/lessons/this-props/exercises/pass-props-component) ::: In PropsDisplayer.js, ``` import React from 'react'; function PropsDisplayer(props) { const stringProps = JSON.stringify(props); return ( <div> <h1>CHECK OUT MY PROPS OBJECT</h1> <h2>{stringProps}</h2> </div> ); } export default PropsDisplayer; ``` :star: The JSON.stringify() static method converts a JavaScript value to a JSON string. In Apps.js, ``` import React from 'react'; import ReactDOM from 'react-dom'; import PropsDisplayer from './PropsDisplayer'; function App() { return <PropsDisplayer myProp = "Hello"/>; } export default App; ``` ## Event Handler as a prop :::success 使用prop串聯多個js的練習。有四個js,index.js負責顯示,app.js是最終集大成,talker.js負責顯示內容,button.js定義UI及行為。 ::: In Button.js, ``` import React from 'react'; function Button(props) { return ( <button onClick = {props.msg}> Click me! </button> ); } export default Button; ``` In Talker.js, ``` import React from 'react'; import Button from './Button'; function Talker() { function speech() { let speech = ''; for (let i = 0; i < 10000; i++) { speech += 'blah '; } alert(speech); } return <Button msg={speech}/>; //{speech}是吃上面speech()function } export default Talker; ``` ## props.children :::success * Every component’s props object has a property named children. * props.children will return everything in between a component’s opening and closing JSX tags. * source: [props.children](https://www.codecademy.com/courses/learn-react-introduction/lessons/this-props/exercises/props-children) ::: ## props exericese :star: :::success source: [props review](https://www.codecademy.com/courses/learn-react-introduction/lessons/this-props/exercises/props-recap) ::: For further practice, consider the following challenge: Create a simple online grocery store with reusable React function components. Your store should provide users with at least four buttons for possible items they can purchase. Every time a user clicks on a button, it should alert that the thing they’ve clicked on has been added to the cart via an alert message. 1. Click on the folder icon next to the App.js file and create a GroceryItem.js file. 1. Define a GroceryItem function component. 1. The component should accept props and return a button that displays the grocery item’s name and contain an event handler for the onClick event. 1. The component should be used to render the four grocery items, passing in the appropriate props. 1. In App.js, return four instances of the GroceryItem component with names such as Eggs, Banana, Strawberry, or Bread. The items are up to you! import React from 'react'; import ReactDOM from 'react-dom'; import GroceryItem from './GroceryItem'; In App.js, ``` function App() { return ( <div> <GroceryItem item='egg' /> <GroceryItem item='banana' /> <GroceryItem item='straberry' /> <GroceryItem item='Bread' /> </div> ) } export default App ``` In GroceryItem.js, ``` import React from "react"; function GroceryItem(props) { function handleClick() { alert(`This is ${props.item}`); } return <button onClick={handleClick}>{props.item}</button>; } export default GroceryItem; ``` ## Hooks :::success Hook主要是用於不需要class 就能輕鬆使用state 的方式。 出現的動機主要是避免開發人員對於class 的this 定義容易混淆,且將使用邏輯更容易直接上手 useState 取代 this.state source: [Why use Hooks?](https://www.codecademy.com/courses/react-101/lessons/the-state-hook/exercises/why-use-hooks);[Hooks at a Glance](https://legacy.reactjs.org/docs/hooks-overview.html) ::: ## state hook 1. 首先須 `import React, { useState } from 'react';` 2. `const[cart,setCart] = useState();` cart是current value, setCart是function 3. `const [color, setColor] = useState("Tomato");` intialize useState with a value :star:使用Boolean判斷是否變換狀態 ** 這屬於"inline event handler" ``` import React, { useState } from 'react'; function ToggleLoading() { const [isLoading, setIsLoading] = useState(); return ( <div> <p>The data is {isLoading ? 'Loading' : 'Not Loading'}</p> <button onClick={() => setIsLoading(true)}> Turn Loading On </button> <button onClick={() => setIsLoading(false)}> Turn Loading Off </button> </div> ); } ``` ------- :star:定義state setter outside JSX ``` import React, { useState } from 'react'; export default function EmailTextInput() { const [email, setEmail] = useState(''); const handleChange = (event) => { const updatedEmail = event.target.value; setEmail(updatedEmail); } return ( <input value={email} onChange={handleChange} /> ); } ``` ## 簡化Event handler寫法 ``` const handleChange = (event) => { const newEmail = event.target.value; setEmail(newEmail); } ``` 簡化為 `const handleChange = (event) => setEmail(event.target.value);` <span style='color:tomato'> handleChange function中,有個local variable名為event,event.target回傳event發生的位置(例如body html),event.target.value取得事件發生位置使用者輸入的值,例如在姓名欄位輸入姓名。這整包setEmail function會update為email。 </span> 或是使用**object restructuring** `const handleChange = ({target}) => setEmail(target.value);` ## Event listener * onChange: calls an event handler each time the user types something in this element.