Key Design Decisions in React.js App Development
React.js is a powerful front-end framework developed by Facebook, offering solutions to common issues like complex event handling and DOM manipulation. By focusing on components and minimizing state management, React.js simplifies development and promotes good design practices.
Download Presentation
Please find below an Image/Link to download the presentation.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.
E N D
Presentation Transcript
React.js SWEN-344 WEB ENGINEERING
Issues with DOM Manipulation DOM manipulation via JQuery or other vanilla JS does not scale well No enforced class structure Event handling is entirely up to you Updating UI is entirely up to you Leads to complex event handling routines Single-Page Applications are difficult with this approach No clean syntax for putting DOM definitions inside JS Response: SPA frameworks e.g. React.js, Angular.js, Vue.js, Ember.js Define everything as components Define connections between them Auto-update everything Hardly ever refresh the (full) page
React.js Built by Facebook Used by over 380,000 sites currently Source: https://trends.builtwith.com/javascript/React A sordid open source license history Used to have concerning language around software patents Today, React.js is MIT-Licensed (yay!) Totally fine to use now Added syntax to Javascript, called JSX Goal: specify DOM in HTML-ish syntax Cleaner syntax, but can be a tad confusing Why React.js in this class? Why not Plus, it s a common/ popular framework currently in use in the industry Give a good intro into components
Key Design Decisions in a React.js App State should be minimal You should never have to sync from one state to another Instead, props react to changes in state Similar concept of DRY and database normalization Where you hold your state Immutability leads to good design practices
JSX and component classes JSX is an extended Javascript based language used by React.js JSX enables writing html tags within javascript functions When you see class MyReactComponent extends React.Component { render() { return ( class allows component to retain state JSX <div>SWEN-344 React Assignment</div> ); extension } } export default MyReactComponent;
Using functions: lambda (arrow) or standard # Or regular function definition You can use class definitions for complex components, or use lambdas for simple HTML returns and stateless components import React from 'react ; function MyComponent () { return ( <div>SWEN-344 React Assignment</div> ); } export default MyComponent; e.g. import React from 'react'; const MyComponent =() => { return ( <div>SWEN-344 React Assignment</div> ); } export default MyComponent; #NOTE: No render function
Original React (Classic Coke style) Classes Fully encapsulate a component Classes contain all functionality to Render a component Handle events Manage the component state
New React (although Classes remain) Functions define components for rendering You can have many functions in a file The Default function is what is rendered Other functions can also be rendered by the default function Functions can also use state; state can be defined (and should be) inside a function Any function starting with use is called a hook Multiple hooks useState is for state data useEffect is for additional rendering effects (also called side-effects useRef is for references to other objects
What React says about effects Effects let a component connect to and synchronize with external systems. This includes dealing with network, browser DOM, animations, widgets written using a different UI library, and other non-React code. useEffectconnects a component to an external system. Effects are an escape hatch from the React paradigm. Don t use Effects to orchestrate the data flow of your application. From <https://react.dev/reference/react/hooks>
What React says about refs Best practices for refs Following these principles will make your components more predictable: Treat refs as an escape hatch. Refs are useful when you work with external systems or browser APIs. If much of your application logic and data flow relies on refs, you might want to rethink your approach. From <https://react.dev/learn/referencing-values-with-refs>
Other cautions Poor design == deductions Whether it s class/ component or functional, points will be deducted for bad usage of the design paradigm Unfortunately, functions and esp. hooks makes it easier to design poorly (see prior slides) The final exam WILL be class/ component based, and you will NOT be allowed to change the structure of the starter code So, learn class/ component as well
Side-By-Side class Page extends Component export function MyPage() { const [menuValue, setMenuSelection] = useState("") function menuSelection(value) { setMenuSelection(value); } { render() { return( <div> return( <div> <Headings></Headings> <Controls menuSelection={menuValue}></Controls> {/*Pass props just like normal */} <div className="flex-container"> <Menu selectionCallback={menuSelection}></Menu> </div> </div> ) } <Headings /> <Controls /> </div> ) } } export default Page;
Side-By-Side export class Controls extends Component { constructor(props) { super(props); this.state = {counter:0}; } doSomething=()=> { alert("Ouch, you clicked me!") this.setState({counter: ++this.state.counter}); } render() { return( <div class="flex-container"> <div class="col1"> Here's one thing </div> <div class="col2"> <input type="text" id="id_text" value="This another thing" /> </div> <div class="col3"> <input type="button" value="Click me" onClick={this.doSomething} /> </div> <Counter count={this.state.counter}></Counter> </div> ) } } //Looks a lot like a class, doesn't it? export function Controls(props) { console.log("Start of Controls") //State has to be INSIDE the function that uses it (like a class variable) //Instead of calling 'setState', this defines the state variable (colour) and the updateMethod (setColour) const [colour, setColour] = useState(""); //Event handlers have to be local functions INSIDE the function that generates the event (i.e. a class method) function handleClick(e) { alert('Ouch, you clicked me!') setColour('green'); } let text = 'This is another thing'; if (props.menuSelection != '') text = props.menuSelection; return( <div className="flex-container"> <div style={{color: colour}} className='col1'>Here's one thing</div> <input className='col2' type='text' value={text}></input> <input className='col3' type='button' value='Click me' onClick={handleClick}></input> </div> ) }
Under The Hood <div className="shopping-list"> return React.createElement('div , <h1>Shopping List for {this.props.name}</h1> {className: 'shopping-list'}, <ul> React.createElement('h1', /* ... h1 children ... */), <li>Instagram</li> React.createElement('ul', /* ... ul children ... */) <li>WhatsApp</li> <li>Oculus</li> ); </ul> </div> React generates code from the JSX that you write
Anatomy of a React app If index.js is the file first loaded (is used to generate index.html) import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorke r'; Index.js will render the component called App If you replace App with any other component, those will be rendered Uppercase tags are assumed to be React JSX ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') ); <React.StrictMode> <MyTextArea /> <MyForm /> <Pictures /> </React.StrictMode>,
Anatomy of a React app <React.StrictMode> class MyTextArea extends React.Component { render() { return ( <div> <MyTextArea /> <MyForm /> <Pictures /> <div>SWEN-344 React Assignment</div> </React.StrictMode>, <textarea>This is my textarea</textarea> </div> ); } }
Anatomy of a React app <React.StrictMode> The idea with React, is to create components for each control (or group of controls) and place them in separate .js files so they can render independently Here, you would have 3 files: - MyTextArea.js - MyForm.js - Pictures.js Each with their own render code <MyTextArea /> <MyForm /> <Pictures /> </React.StrictMode>,
From html to React One way to think of this is to take each major section of your html, and create a class with a render function, and move the html inside the render function class MyHeading extends Component { render() { return ( <div> <div>SWEN-344 React Assignment</div> <textarea>This is my textarea</textarea> </div> ); } } <body> <div>SWEN-344 React Assignment</div> <textarea>This is my textarea</textarea> </body> //In App.js function App() { return ( <MyHeading /> );}
Javascript? End state: Convert to JSX events and arrow functions as event handlers Step 1: (Just Starting out): You can add your old .js file in public/index.html, and call methods using: onClick={window.functionName} or onClick = {() => window.functionName( param string )} Step 2: (For Client-2): Convert to JSX events doButtonFunction =() => { //some code here. This is a member fn. in the component class } <button type="button" className="action onClick={this.doButtonFn}>+</button>
State & Properties State is read-write Properties is read-only Every part of the UI is represented once in state. For us, this generally means state is help by the top-level component But, for bigger projects having mutually-exclusive states separately improves maintainability State gets passed to props on child components Every component has a render() Usually: render based on properties Child components update whenever the state changes State changes trigger updates Updates are all handled by a react runtime in the background
State State is very important in React. The only way react knows to re-render components (e.g., your webpage) is that it detects a change in state. The primary way it detects changes in state is by looking at the state attributes you have defined and detect when their value is different than it was in a previous state This can only be done if it knows (i.e., stores) what the prior state was React encourages the use of this.setState().This tells react that the state will change and, thus, a re-render is required State is private to components that it is defined in Use props to pass information about state (future slide)
Setting State Board has two attributes in its state: squares and xIsNext. Whenever we change either of these, we should use this.setState(). For example: class Board extends React.Component { constructor(props) { this.setState({ super(props); squares: array(9).fill(5), this.state = { xIsNext: !this.state.xIsNext, squares: Array(9).fill(null), }) xIsNext: true, This will inform react that the state is being modified so that it will re-render after we have finished modifying the state. } }; } Example of a class component with a state containing two attributes.
Properties Properties is a way for a component to receive data (e.g., state data) from its parent. function Square(props) { return ( <button className="square" onClick={props.onClick} renderSquare(i) { return ( <Square > value={this.state.squares[i]} onClick={() => this.handleClick(i)} {props.value} </button> /> ); ) } } Notice the props parameter. We can access both onclick and value through props . Notice that square has two properties passed to it from its parent: value and onClick.
Events React supports different types of events You can set these as properties just like in HTML https://reactjs.org/docs/events.html renderSquare(i) { return ( onClick <Square onContextMenu value={this.state.squares[i]} onDoubleClick onClick={() => this.handleClick(i)} Event naming convention is: on[Event] /> NOTE: camelCase is required! ) } Also for className ) }
this Prefer arrow functions when setting up events in react. It avoids known, squirrely semantics of how javascript deals with its `this` pointer. The details boil down to how javascript determines the value of `this`. In short, the value of `this` is determined by the object on which `this` is called If you do something like obj.method(), this will be obj regardless of where method() was defined (remember, javascript allows you to add methods dynamically). This is bad if `this` was referring to some other object we wanted to use `this` to access Arrow functions are an exception they inherit `this` from their parent scope when the function is originally defined, so even if you reassign method(), `this` will not change what it refers to Some articles if you re interested: https://yehudakatz.com/2011/08/11/understanding-javascript-function- invocation-and-this/ https://frontarm.com/james-k-nelson/when-to-use-arrow-functions/
Magical Moving this Example: const myObject = { myMethod: () => { //Love to see it console.log(this); } }; const myObject = { myMethod: function () { //DANGER console.log(this); } }; // this === window or global object myObject.myMethod() const myMethod = myObject.myMethod; // this === myObject!!!!OhnoXXX myObject.myMethod() const myMethod = myObject.myMethod; // this === window or global object myMethod() // this === window or global object myMethod()
Tips Comments in React To build static files: npm run build {/* This is a comment*/} You can run react as a local server on the command line. This runs the server on localhost:3000 This generates .html files and all dependencies and puts them in the build directory From here, you can view files using your browser i.e. npm start
The React way In this way, a parent can apply higher level knowledge to update the behaviour of a child component Parent State update event communicated using callback props callbacks render event Child Another child
Sample class App extends React.Component{ constructor(props){ super(props); this.state = {buttonText: "default text"} } class XButton extends React.Component{ handler = () => { this.props.callParent(); } appHandler = () => { this.setState({buttonText:"Click me again!"}) } render() { return ( <div className="App"> <XButton text={this.state.buttonText} colour=" blue" callParent={this.appHandler}></XButton> </div> ); } } render(){ return ( <input type='button' value={this.props.text} style={{color:this.props.colour, width:100, height:100 }} onClick={this.handler}></input> ) } }
CSS CSS style .App-header2 { <div className="App"> background-color: #282c34; <div className="App-header2">React example</div> min-height: 10vh; <XButton text={this.state.buttonText} colour="blue display: flex; callParent={this.appHandler}></XButton> flex-direction: column; </div> align-items: center; justify-content: center; font-size: calc(10px + 2vmin); color: white; } You can also use React modules (ref: https://www.w3schools.com/react/react_css.asp )
Side note React has two implementation models React components (basically classes) functions/ hooks We will stick with React components Students will be expected to implement in the component model for the project and practica
But a few insights There is nothing purely evil about function/ hooks, however function/ hook style simplifies a few things (some syntactic sugar and some legitit9mate complexity resolution in unusual cases) But it makes it easy to start designing badly ( a trap which many novice developers fall into) Reactjs official docs refer to useState, useEffect, refs as escape hatches use only in extreme cases In our class if you overuse use it, you will likely lose points for bad design See slides (React evolution) for more info
A few more React+js tips Passing params to event handlers onClick={() => jsFunction(param) } Note camelCase required for JSX (onClick vs onclick) Note the curly-brace required to insert JSX in the HTML For class based components Use this.xxx, else variables and functions will be undefined Do NOT do this onClick={jsFunction(param) } Nothing will happen, it will be treated as a new fn. declaration! Preferred style for event methods in classes is => function (to avoid this. Ambiguity) You can do callbacks (child->parent) using props i.e. a prop can be a variable OR a function
A few more React+js tips Other params to event handlers onChange={ this.jsFunction } jsFunction = (e) => { //For most events, the event target is AUTOMATICALLY passed to the event handler //This means you can use e.target to get the value (or other attribute from that parameter! console.log(e.target.value); }
A few more React+js tips In JSX, inline styles must be camelCase as well (if you have to use them) e.g. borderRadius vs border- radius e.g. style={{borderRadius: "10px;"}} Note the double curly-brace format JSX prefers className vs class (although both seem to work) All JSX return() functions require a single containing <div> -- refactor accordingly While you can get away w/o closing tags for <input> and <br> etc., in HTML, you cannot in JSX Beware of capitalization: <MyComponent> vs. <myComponent> Do NOT use document.getElementById to manipulate the DOM!! It s all about state and props and components!
Recap React components should be self-contained and self-configuring Pass props to components so they CAN configure themselves State should be carefully managed in components which need to modify behaviour and have access to information to define the new behaviour (part of coherence and enscapsulation) React does not expect any use of brute-force access to the DOM (i.e. no getElementById from random components to get to other components - Use props, events, callbacks to communicate, and then modify state, which will trigger re- render and send new values for props
React Developer Tools Chrome and Firefox both have React Developer Tools addons. Highly recommended that you install these to make debugging react components simpler. It allows you to debug JSX/Code written using react directly instead of having to debug the resulting generated code. Firefox: https://addons.mozilla.org/en-US/firefox/addon/react-devtools/ Chrome: https://chrome.google.com/webstore/detail/react-developer- tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en
Demo Topics Components State Props JSX