# 08-More of ReactJS In this week, we will continue learning ReactJS. ## Conditional Rendering Conditional rendering is a term to describe the ability to render different user interface (UI) markup if a condition is true or false. In React, it allows us to render different elements or components based on a condition. Example: Simplest and not recommended way ``` import React, { Component } from 'react'; class ShowHide extends Component { constructor() { super() this.state = { showMsg: false } this.showHide = this.showHide.bind(this) } showHide() { this.setState({ showMsg: !this.state.showMsg }) } render() { let { showMsg } = this.state if (showMsg) { return <div> <button onClick={this.showHide}>Show/Hide</button> <h1>Hello, there</h1> </div> } else { return <div> <button onClick={this.showHide}>Show/Hide</button> </div> } } } export default ShowHide; ``` Using shortcut syntax of if...else ``` import React, { Component } from 'react'; class ShowHide extends Component { constructor() { super() this.state = { showMsg: false } this.showHide = this.showHide.bind(this) } showHide() { this.setState({ showMsg: !this.state.showMsg }) } render() { let { showMsg } = this.state return <div> <button onClick={this.showHide}>Show/Hide</button> {showMsg ? <h1>Hello, there</h1> : null} </div> } } export default ShowHide; ``` above code considered bulky, ugly, or not readable, but it is the most used by the most developers. Let's make it better using Logical && (Short Circuit Evaluation): ``` import React, { Component } from 'react'; class ShowHide extends Component { constructor() { super() this.state = { showMsg: false } this.showHide = this.showHide.bind(this) } showHide() { this.setState({ showMsg: !this.state.showMsg }) } render() { let { showMsg } = this.state return <div> <button onClick={this.showHide}>Show/Hide</button> {showMsg && <h1>Hello, there</h1>} </div> } } export default ShowHide; ``` ## Component Lifecycle Each component has several lifecycle methods that you can override to run code at particular times in the process. ![](https://i.imgur.com/LebDbHf.png) * **Mounting** Mounting means putting elements into the DOM. React has four built-in methods that gets called, in this order, when mounting a component: 1. constructor() 2. getDerivedStateFromProps() 3. render() 4. componentDidMount() The render() method is required and will always be called, the others are optional and will be called if you define them. Example: ``` import React, { Component } from 'react'; class ShowHide extends Component { constructor(props) { super(props)// props should be passed to superclass this.state = { // init state showMsg: false } this.showHide = this.showHide.bind(this) // bninding function to this class } // this executed after constructor and before render functions static getDerivedStateFromProps(props, state) { console.log(props) // old one console.log(state) // old one return { // return new values of the state showMsg:true } } showHide() { this.setState({ showMsg: !this.state.showMsg }) } render() { console.log('rendering after getDerivedStateFromProps function', this.state) let { showMsg } = this.state return <div> <button onClick={this.showHide}>Show/Hide</button> {showMsg && <h1>Hello, there</h1>} </div> } } export default ShowHide; ``` * **Updating** The next phase in the lifecycle is when a component is updated. A component is updated whenever there is a change in the component's state or props. React has five built-in methods that gets called, in this order, when a component is updated: 1. getDerivedStateFromProps() 2. shouldComponentUpdate() 3. render() 4. getSnapshotBeforeUpdate() 5. componentDidUpdate() The render() method is required and will always be called, the others are optional and will be called if you define them. ``` import React, { Component } from 'react'; class ShowHide extends Component { constructor(props) { super(props)// props should be passed to superclass this.state = { // init state showMsg: false } this.showHide = this.showHide.bind(this) // bninding function to this class console.log('constructor') } // this function added to understand how component will not changed on update! shouldComponentUpdate() { return false; } // this executed after constructor and before render functions static getDerivedStateFromProps(props, state) { console.log('getDerivedStateFromProps') console.log(props) // old one console.log(state) // old one return { // return new values of the state showMsg:true } } showHide() { this.setState({ showMsg: !this.state.showMsg }) } render() { console.log('render') console.log('rendering after getDerivedStateFromProps function', this.state) let { showMsg } = this.state return <div> <button onClick={this.showHide}>Show/Hide</button> {showMsg && <h1>Hello, there</h1>} </div> } componentDidMount() { console.log('componentDidMount') console.log("Executed after render function and after component amounted to the DOM") console.log('Here you can make heavy & side effetcs tasks') } } export default ShowHide; ``` * **Unmounting** The next phase in the lifecycle is when a component is removed from the DOM, or unmounting as React likes to call it. React has only one built-in method that gets called when a component is unmounted: 1. componentWillUnmount() ## ReactJS Hooks Hooks are the new feature introduced in the React 16.8 version. It allows you to use state and other React features without writing a class. Hooks are the functions which "hook into" React state and lifecycle features from function components. It does not work inside classes. We can simply imagine as it the migration from class component to functional and make the latest one to be used as statefull component with additional capabilities and features. ### useState() There is no constructor function and instead of that we can use useState() function inside the function component to create and manage states of the component. Example: ``` import React, { useState } from 'react'; function CountApp() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } export default CountApp; ``` ### useEffect() The Effect Hook allows us to perform side effects (an action) in the function components. It does not use components lifecycle methods which are available in class components. In other words, Effects Hooks are equivalent to componentDidMount(), componentDidUpdate(), and componentWillUnmount() lifecycle methods. Side effects have common features which the most web applications need to perform, such as: * Updating the DOM, * Fetching and consuming data from a server API, * Setting up a subscription, etc. Example: ``` import React, { useState, useEffect } from 'react'; function CounterExample() { const [count, setCount] = useState(0); // Similar to componentDidMount and componentDidUpdate: useEffect(() => { // Update the document title using the browser API document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); } export default CounterExample; ``` **Others important built-in hooks:** useContext useReducer useCallback useMemo useRef ## SPA & Routing SPA stands for Single Page Application. It is a very common way of programming websites these days. The idea is that the website loads all the HTML/JS the first time you visit. When you then navigate, the browser will only rerender the content without refreshing the website. **React-router-dom package** React Router is a fully-featured client and server-side routing library for ReactJS. React Router runs anywhere React runs; on the web, on the server with node.js, and on React Native. - Install dependencies https://www.npmjs.com/package/react-router-dom ``` npm install react-router-dom ``` Example: Github Repo https://github.com/ProgFadi/giz-rrd.git There are three primary categories of components in React Router: * routers, like <BrowserRouter> and <HashRouter> * route matchers, like <Route> and <Switch> * and navigation, like <Link>, <NavLink>, and <Redirect> ![](https://i.imgur.com/ZsOUZ7e.png) **BrowserRouter** is a router implementation that uses the HTML5 history API(pushState, replaceState and the popstate event) to keep your UI in sync with the URL. It is the parent component that is used to store all of the other components. **Route** is the conditionally shown component that renders some UI when its path matches the current URL. **Link:** Link component is used to create links to different routes and implement navigation around the application. It works like HTML anchor tag. **Switch:** Switch component is used to render only the first route that matches the location rather than rendering all matching routes. Although there is no defying functionality of SWITCH tag in our application because none of the LINK paths are ever going to coincide. But let’s say we have a route (Note that there is no EXACT in here), then all the Route tags are going to be processed which start with ‘/’ (all Routes start with /). This is where we need SWITCH statement to process only one of the statements. **Let's create an example like above repo mentioned.** -------------------------------------------------------------------------- ## React Developer Tool React Developer Tools is a Chrome DevTools extension for the open-source React JavaScript library. It allows you to inspect the React component hierarchies in the Chrome Developer Tools. You will get two new tabs in your Chrome DevTools: "⚛️ Components" and "⚛️ Profiler". ## Code Snippets in VSCode Code snippets are templates that make it easier to enter repeating code patterns, such as loops or conditional-statements. In Visual Studio Code, snippets appear in IntelliSense (Ctrl+Space) mixed with other suggestions, as well as in a dedicated snippet picker (Insert Snippet in the Command Palette). There is also support for tab-completion: Enable it with "editor.tabCompletion": "on", type a snippet prefix (trigger text), and press Tab to insert a snippet. ### Built-in snippets VS Code has built-in snippets for a number of languages such as: JavaScript, TypeScript, Markdown, and PHP. ### Install snippets from the Marketplace Many extensions on the VS Code Marketplace include snippets.You can search for extensions that contains snippets in the Extensions view (Ctrl+Shift+X) using the `@category:"snippets"` filter. ### What is a snippet? Snippets are small chunks of re-usable code, or code that you may see several times in a program with difference circumstances. Some commonly used examples: the forEach loop, add_column etc in a rails migration, and html boilerplate. ### Create your own snippets You can easily define your own snippets without any extension. #### Syntax of a snippet **Snippet Name:** this is what is displayed via Itellisense Prefix: the trigger word for intellisense recognizing that you want this snippet. **Body:** the content of the snippet. i.e. how you want the code to look when you tab complete. **Description:** An optional description of the snippet you would like to display in the tool tip of intellisense. #### Steps to create "" - Step1: Navigate to File > Preferences > Code Snippets - Step2: Choose Language (Ex:JS). - Step3: Add your template at the end of list in the .Json file. Example: ``` "Fast Loop":{ "prefix": "floop", "body":[ "for(let ${1:item} of ${2:array})", "{\t", "$3", "}" ], "description": "This is a custom snippet" } ``` In the example above: "Fast Loop" is the snippet name. It is displayed via IntelliSense if no description is provided. prefix defines one or more trigger words that display the snippet in IntelliSense. Substring matching is performed on prefixes, so in this case, "fl" could match "fast loop". body is one or more lines of content, which will be joined as multiple lines upon insertion. Newlines and embedded tabs will be formatted according to the context in which the snippet is inserted. description is an optional description of the snippet displayed by IntelliSense. Additionally, the body of the example above has three placeholders (listed in order of traversal): ${1:item}, ${2:array}, and $0. You can quickly jump to the next placeholder with Tab, at which point you may edit the placeholder or jump again the next one. The string after the colon (if any) is the default text, for example element in ${2:array}. Placeholder traversal order is ascending by number, starting from one; zero is an optional special case that always comes last, and exits snippet mode with the cursor at the specified position. ## Prop Types Properties validation is a useful way to force the correct usage of the components. This will help during development to avoid future bugs and problems, once the app becomes larger. It also makes the code more readable, since we can see how each component should be used. Example: ``` import React from 'react'; class App extends React.Component { render() { return ( <div> <h3>Array: {this.props.propArray}</h3> <h3>Bool: {this.props.propBool ? "True..." : "False..."}</h3> <h3>Func: {this.props.propFunc(3)}</h3> <h3>Number: {this.props.propNumber}</h3> <h3>String: {this.props.propString}</h3> <h3>Object: {this.props.propObject.objectName1}</h3> <h3>Object: {this.props.propObject.objectName2}</h3> <h3>Object: {this.props.propObject.objectName3}</h3> </div> ); } } App.propTypes = { propArray: React.PropTypes.array.isRequired, propBool: React.PropTypes.bool.isRequired, propFunc: React.PropTypes.func, propNumber: React.PropTypes.number, propString: React.PropTypes.string, propObject: React.PropTypes.object } App.defaultProps = { propArray: [1,2,3,4,5], propBool: true, propFunc: function(e){return e}, propNumber: 1, propString: "String value...", propObject: { objectName1:"objectValue1", objectName2: "objectValue2", objectName3: "objectValue3" } } export default App; ``` **Note:** for performance reasons, PropTypes is only checked in development mode. **Note:** you need to install package "prop-types". ## Material UI framework. Enable you to build your own design system and develop React applications faster. It is self-supporting, simple, declarative components. Get Started ### Installation ``` npm install @mui/material ``` ### Basic Usage ``` import * as React from 'react'; import ReactDOM from 'react-dom'; import Button from '@mui/material/Button'; function App() { return <Button variant="contained">Hello World</Button>; } ReactDOM.render(<App />, document.querySelector('#app')); ``` ## References React-Router-Dom v6 https://medium.com/@manishsundriyal/whats-new-in-react-router-v6-20eefe665be9 Npm Package: https://www.npmjs.com/package/react-router-dom React Developer Tools https://reactjs.org/blog/2015/09/02/new-react-developer-tools.html MUI: https://mui.com/