# Learn react.js ###### tags: `react` A note of codecademy React class ## JSX ```javascript const h1 = <h1>Hello world</h1>; ``` The part that looks like HTML, `<h1>Hello world</h1>`, is something called JSX. JSX is a syntax extension for JavaScript. It was written to be used with React. JSX code looks a lot like HTML. ### JSX also has attributes ```javascript const panda = <img src='images/panda.jpg' alt='panda' width='500px' height='500px' />; ``` ### Nest If a JSX expression takes up more than one line, then you must wrap the multi-line JSX expression in parentheses. ```javascript const myDiv = ( <div> <h1> Hello world </h1> </div> ); ``` ### JSX Outer Elements this code will work: ```javascript const paragraphs = ( <div id="i-am-the-outermost-element"> <p>I am a paragraph.</p> <p>I, too, am a paragraph.</p> </div> ); ``` But this code will not work: ```javascript const paragraphs = ( <p>I am a paragraph.</p> <p>I, too, am a paragraph.</p> ); ``` ## Render ``` import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render(<h1>Hello world</h1>, document.getElementById('app')); ``` ReactDOM.render() is the most common way to render JSX. It takes a JSX expression, creates a corresponding tree of DOM nodes, and adds that tree to the DOM. ### Virtual DOM One special thing about ReactDOM.render() is that it only updates DOM elements that have changed. That means that if you render the exact same thing twice in a row, the second render will do nothing: ```javascript const hello = <h1>Hello world</h1>; // This will add "Hello world" to the screen: ReactDOM.render(hello, document.getElementById('app')); // This won't do anything at all: ReactDOM.render(hello, document.getElementById('app')); ``` ### Class In JSX, you can’t use the word class! You have to use className instead: ```javascript <h1 className="big">Hey</h1> ``` ### Self-closing tag ``` Fine in JSX: <br /> NOT FINE AT ALL in JSX: <br> ``` ### javascript in JSX ``` // will display 2 + 3 ReactDOM.render( <h1>2 + 3</h1>, document.getElementById('app') ); // will display 5 ReactDOM.render( <h1>{2 + 3}</h1>, document.getElementById('app') ); ``` The curly braces themselves won’t be treated as JSX nor as JavaScript. They are markers that signal the beginning and end of a JavaScript injection into JSX, similar to the quotation marks that signal the boundaries of a string. ```javascript const url = 'https://image.com/example.jpg' const imgElement = <img src={url}/> ReactDOM.render(imgElement, document.getElementById('imgContainer')) ``` ### Event Listeners in JSX [available events](https://reactjs.org/docs/events.html#supported-events) Note that in HTML, event listener names are written in all lowercase, such as onclick or onmouseover. In JSX, event listener names are written in camelCase, such as onClick or onMouseOver. ```javascript function myFunc() { alert('Make myFunc the pFunc... omg that was horrible i am so sorry'); } <img onClick={myFunc} /> ``` ### JSX Conditionals: If Statements That Don't Work ```javascript // NOT OK ( <h1> { if (purchase.complete) { 'Thank you for placing an order!' } } </h1> ) ``` [dive into the reason at underhood](https://reactjs.org/docs/jsx-in-depth.html) ### The ternary operator works ```javascript // OK const headline = ( <h1> { age >= drinkingAge ? 'Buy Drink' : 'Do Teen Stuff' } </h1> ); ``` ### JSX Conditionals: && If true, show the right ```javascript const tasty = ( <ul> <li>Applesauce</li> { !baby && <li>Pizza</li> } { age > 15 && <li>Brussels Sprouts</li> } { age > 20 && <li>Oysters</li> } { age > 25 && <li>Grappa</li> } </ul> ); ``` ### .map ```javascript const strings = ['Home', 'Shop', 'About Me']; const listItems = strings.map(string => <li>{string}</li>); ReactDOM.render(<ul>{listItems}</ul>, document.getElementById('app')) ``` ### key ```javascript const peopleLis = people.map((person, i) => // expression goes here: <li key={'person_' + i}>{person}</li> ); ``` Not all lists need to have keys. A list needs keys if either of the following are true: - The list-items have memory from one render to the next. For instance, when a to-do list renders, each item must “remember” whether it was checked off. The items shouldn’t get amnesia when they render. - A list’s order might be shuffled. For instance, a list of search results might be shuffled from one render to the next. ### React.createElement ```javascript= // These 2 are same const myDiv = <div>i am div</div> const myDiv = React.createElement('div',null,'i am div'); ``` ## Component ```javascript import React from 'react'; import ReactDOM from 'react-dom'; class MyComponentClass extends React.Component { render() { return <h1>Hello world</h1>; } }; ReactDOM.render( <MyComponentClass />, document.getElementById('app') ); ``` ### Import React ```javascript import React from 'react'; ``` This creates an object named React which contains methods necessary to use the React library. ```javascript import ReactDOM from 'react-dom'; ``` The methods imported from 'react-dom' are meant for interacting with the DOM. You are already familiar with one of them: ReactDOM.render(). To clarify: the DOM is used in React applications, but it isn’t part of React. After all, the DOM is also used in countless non-React applications. Methods imported from 'react' are only for pure React purposes, such as creating components or writing JSX elements. ### Create Component instance ```javascript import React from 'react'; import ReactDOM from 'react-dom'; class MyComponentClass extends React.Component { render() { return <h1>Hello world</h1>; } } // component goes here: <MyComponentClass /> ``` ## Advanced ### Use this in a Component ```javascript class IceCreamGuy extends React.Component { get food() { return 'ice cream'; } render() { return <h1>I like {this.food}.</h1>; } } ``` You don’t need those parentheses because .food is a getter method. You can tell this from the get in the above class declaration body. There’s nothing React-specific about getter methods, nor about this behaving in this way! However, in React you will see this used in this way almost constantly. [more about this](https://dmitripavlutin.com/gentle-explanation-of-this-in-javascript/) ### Use an Event Listener in a Component ```javascript class MyClass extends React.Component { myFunc() { alert('Stop it. Stop hovering.'); } render() { return ( <div onHover={this.myFunc}> </div> ); } } ``` ## Components Interact What makes React special is the ways in which components interact. ### import custom component ```javascript import ReactDOM from 'react-dom'; import { NavBar } from './NavBar.js'; ``` If you use an import statement, and the string at the end begins with either a dot or a slash, then import will treat that string as a filepath. import will follow that filepath, and import the file that it finds. If your filepath doesn’t have a file extension, then “.js” is assumed. So the above example could be shortened: ```javascript import { NavBar } from './NavBar'; ``` ### export When you import a variable from a file that is not the current file, then an import statement isn’t quite enough. You also need an export statement, written in the other file, exporting the variable that you hope to grab. export comes from ES6’s module system, just like import does. export and import are meant to be used together, and you rarely see one without the other. You can export multiple things from the same file: // Manifestos.js: ```javascript export const faveManifestos = { futurist: 'http://www.artype.de/Sammlung/pdf/russolo_noise.pdf', agile: 'https://agilemanifesto.org/iso/en/manifesto.html', cyborg: 'http://faculty.georgetown.edu/irvinem/theory/Haraway-CyborgManifesto-1.pdf' }; export const alsoRan = 'TimeCube'; ``` In a different file, import the name of the var, let, const, function, or class from the first file: ```javascript // App.js: // Import faveManifestos and alsoRan from ./Manifestos.js: import { faveManifestos, alsoRan } from './Manifestos'; // Use faveManifestos: console.log(`A Cyborg Manifesto: ${faveManifestos.cyborg}`); ``` This style of importing and exporting in JavaScript is known as “named exports.” ### Access a Component's props ``` this.props ``` a component display its props ``` class PropsDisplayer extends React.Component { render() { const stringProps = JSON.stringify(this.props); return ( <div> <h1>CHECK OUT MY PROPS OBJECT</h1> <h2>{stringProps}</h2> </div> ); } } ReactDOM.render(<PropsDisplayer myProp="Hello"/>, document.getElementById('app')) ``` ``` // web display {"myProp":"Hello"} ``` we can pass a.function to b as event handler ### props.children ```javascript export class List extends React.Component { render() { let titleText = `Favorite ${this.props.type}`; if (this.props.children instanceof Array) { titleText += 's'; } return ( <div> <h1>{titleText}</h1> <ul>{this.props.children}</ul> </div> ); } } ``` ```javascript class App extends React.Component { render() { return ( <div> <List type='Living Musician'> <li>Sachiko M</li> <li>Harvey Sid Fisher</li> </List> <List type='Living Cat Musician'> <li>Nora the Piano Cat</li> </List> </div> ); } } ``` result ![](https://i.imgur.com/GP6g16c.png) ### defaultProps ```javascript class Example extends React.Component { render() { return <h1>{this.props.text}</h1>; } } Example.defaultProps = { text: 'default text' }; ``` ## Dynamic Content ### State & Prop There are two ways for a component to get dynamic information: props and state. Besides props and state, every value used in a component should always stay exactly the same. ### Declare State ```javascript class App extends React.Component { constructor(props){ super(props) // requeired this.state = { title: 'Best App' } } render() { return ( <h1> {this.state.title} </h1> ); } } ``` ### setState ```javascript class Mood extends React.Component { constructor(props) { super(props); this.state = { mood: 'good' }; this.toggleMood = this.toggleMood.bind(this); // required } toggleMood() { const newMood = this.state.mood == 'good' ? 'bad' : 'good'; this.setState({ mood: newMood }); } render() { return ( <div> <h1>I'm feeling {this.state.mood}!</h1> <button onClick={this.toggleMood}> Click Me </button> </div> ); } } ``` For an in-depth explanation of this kind of binding trickery, begin with the [React docs](https://reactjs.org/docs/handling-events.html). For the less curious, just know that in React, whenever you define an event handler that uses this, you need to add this.methodName = this.methodName.bind(this) to your constructor function. ### this.setState Automatically Calls render Any time that you call this.setState(), this.setState() AUTOMATICALLY calls .render() as soon as the state has changed. ## Component Lifecycle ![](https://i.imgur.com/mpsNfyz.png) ### display current time ```javascript class Clock extends React.Component { constructor(props){ super(props); this.state = { date: new Date() }; } render(){ return <div>{this.state.date.toLocaleTimeString()}</div> } } ReactDOM.render(<Clock />, document.getElementById('app')); ``` it print out the time but it is static now, which means it won't update the time after it shows up. ```javascript class Clock extends React.Component { constructor(props) { super(props); this.state = { date: new Date() }; } render() { return <div>{this.state.date.toLocaleTimeString()}</div>; } componentDidMount() { // Paste your code here. const oneSecond = 1000; setInterval(() => { this.setState({ date: new Date() }); }, oneSecond); } } ReactDOM.render(<Clock />, document.getElementById('app')); ``` Our clock is working, but it has an important problem. We never told the interval to stop, so it’ll keep running that function forever (or at least, until the user leaves/refreshes the page). When the component is unmounted (in other words, removed from the page), that timer will keep on ticking, trying to update the state of a component that’s effectively gone. This means your users will have some JavaScript code running unnecessarily, which will hurt the performance of your app. React will log a warning that looks something like this: ***Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.*** ```javascript export class Clock extends React.Component { constructor(props) { super(props); this.state = { date: new Date() }; } render() { return <div>{this.state.date.toLocaleTimeString()}</div>; } componentDidMount() { const oneSecond = 1000; this.intervalID = setInterval(() => { this.setState({ date: new Date() }); }, oneSecond); } componentWillUnmount() { clearInterval(this.intervalID); } } ``` ### ComponentDidUpdate can be switched to precise mode ```javascript export class Clock extends React.Component { constructor(props) { super(props); this.state = { date: new Date() }; } render() { return ( <div> {this.props.isPrecise ? this.state.date.toISOString() : this.state.date.toLocaleTimeString()} </div> ); } componentDidMount() { const oneSecond = 1000; this.startInterval(oneSecond); } componentWillUnmount() { clearInterval(this.intervalID); } componentDidUpdate(prevProps) { if (this.props.isPrecise === prevProps.isPrecise) { return; } clearInterval(this.intervalID); let delay = this.props.isPrecise ? 100 : 1000; // ... this.startInterval(delay); } startInterval(delay) { this.intervalID = setInterval(() => { this.setState({ date: new Date() }); }, delay); } } ``` ## Stateless Functional Components ```javascript // A component class written in the usual way: export class MyComponentClass extends React.Component { render() { return <h1>Hello world</h1>; } } // The same component class, written as a stateless functional component: export const MyComponentClass = () => { return <h1>Hello world</h1>; } // Works the same either way: ReactDOM.render( <MyComponentClass />, document.getElementById('app') ); ``` ### Access props at stateless functioncal component ```javascript export const NewFriend = (props) => { return ( <div> <img src={props.src} /> </div> ); } ReactDOM.render( <NewFriend src="https://content.codecademy.com/courses/React/react_photo-squid.jpg" />, document.getElementById('app') ); ``` ### Recap - Function components are React components defined as JavaScript functions - Function components must return JSX - Function components may accept a props parameter. Expect it to be a JavaScript object ## React Hook ### import ```javascript import React, { useState } from 'react'; ``` useState() is a JavaScript function defined in the React library. When we call this function, it returns an array with two values: - current state - the current value of this state - state setter - a function that we can use to update the value of this state ### Update function component state ```javascript export default function ColorPicker() { // call useState and assign its return values to `color` and `setColor` const [color, setColor] = useState(); const divStyle = {backgroundColor: 'purple'}; return ( <div style={{backgroundColor: color}}> <p>The color is {color}</p> <button onClick={()=>setColor('Aquamarine')}> Aquamarine </button> <button onClick={()=>setColor('BlueViolet')}> BlueViolet </button> <button onClick={()=>setColor('Chartreuse')}> Chartreuse </button> <button onClick={()=>setColor('CornflowerBlue')}> CornflowerBlue </button> </div> ); } ``` ### why hook traditional react class couples UI to a component so when we need to decouple the logic and UI, we use hook hook is a function to handle state ## Good shits - https://medium.com/starbugs/%E5%88%9D%E6%8E%A2-server-side-rendering-%E8%88%87-next-js-%E6%8E%A8%E5%9D%91%E8%A8%88%E7%95%AB-d7a9fb48a964 - https://mathiasbynens.be/notes/javascript-identifiers