React js SWEN344 WEB ENGINEERING Issues with DOM
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 ○ ○ ○ 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 ● Response: SPA frameworks
React. js ● Built by Facebook ● Used by over 380, 000 sites currently ○ Source: https: //trends. builtwith. com/javascript/React ○ ○ ○ Used to have concerning language around software patents Today, React. js is MIT-Licensed (yay!) Totally fine to use now ○ ○ Goal: specify DOM in HTML-ish syntax Cleaner syntax, but can be a tad confusing ● A sordid open source license history ● Added syntax to Javascript, called JSX ● 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 My. React. Component extends React. Component { render() { return ( } } <div>SWEN-344 React Assignment</div> ); ‘class’ allows component to retain state JSX extension
Using functions: lambda (arrow) or standard You can use class definitions for complex components, or use lambdas for simple HTML returns and stateless components e. g. import React from 'react'; const My. Component =() => { #NOTE: No ‘render’ function return ( <div>SWEN-344 React Assignment</div> ); } export default My. Component; # Or regular function definition import React from 'react’; function My. Component () { return ( <div>SWEN-344 React Assignment</div> ); } export default My. Component;
Under The Hood <div class. Name="shopping-list"> return React. create. Element('div’, <h 1>Shopping List for {this. props. name}</h 1> <ul> <li>Instagram</li> {class. Name: 'shopping-list'}, React. create. Element('h 1', /*. . . h 1 children. . . */), <li>Whats. App</li> React. create. Element('ul', /*. . . ul children. . . */) <li>Oculus</li> ); </ul> </div> React generates code from the JSX that you write
Anatomy of a React app import React from 'react'; import React. DOM from 'react-dom'; import '. /index. css'; import App from '. /App'; import * as service. Worker from '. /service. W orker'; React. DOM. render( <React. Strict. Mode> <App /> </React. Strict. Mode>, document. get. Element. By. Id('root') ); If index. js is the file first loaded (is used to generate index. html) • Index. js will render the component called App • If you replace App with any other component, those will be rendered <React. Strict. Mode> <My. Text. Area /> <My. Form /> <Pictures /> </React. Strict. Mode>,
Anatomy of a React app <React. Strict. Mode> <My. Text. Area /> <My. Form /> class My. Text. Area extends React. Component { render() { return ( <div> <Pictures /> <div>SWEN-344 React Assignment</div> </React. Strict. Mode>, <textarea>This is my textarea</textarea> </div> ); } }
Anatomy of a React app <React. Strict. Mode> <My. Text. Area /> <My. Form /> <Pictures /> </React. Strict. Mode>, 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: - My. Text. Area. js - My. Form. js - Pictures. js Each with their own ‘render’ code
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 ○ ○ State changes trigger updates Updates are all handled by a react runtime in the background ● Child components update whenever the state changes
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. set. State(). 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 class Board extends React. Component { constructor(props) { super(props); Board has two attributes in its state: squares and x. Is. Next. Whenever we change either of these, we should use this. set. State(). For example: this. set. State({ squares: array(9). fill(5), this. state = { x. Is. Next: !this. state. x. Is. Next, squares: Array(9). fill(null), x. Is. Next: true, } }; } Example of a class component with a state containing two attributes. }) This will inform react that the state is being modified so that it will re-render after we have finished modifying the state.
Properties is a way for a component to receive data (e. g. , state data) from its parent. render. Square(i) { return ( <Square value={this. state. squares[i]} on. Click={() => this. handle. Click(i)} /> ) } Notice that square has two properties passed to it from its parent: value and on. Click. function Square(props) { return ( <button class. Name="square" on. Click={props. on. Click} > {props. value} </button> ); } Notice the ‘props’ parameter. We can access both onclick and value through ‘props’.
Events React supports different types of events You can set these as properties just like in HTML https: //reactjs. org/docs/events. html render. Square(i) { return ( on. Click <Square on. Context. Menu value={this. state. squares[i]} on. Double. Click on. Click={() => this. handle. Click(i)} Event naming convention is: on[Event] /> ) }
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-functioninvocation-and-this/ ○ https: //frontarm. com/james-k-nelson/when-to-use-arrow-functions/
Magical Moving ‘this’ Example: const my. Object = { my. Method: () => { //Love to see it console. log(this); } }; const my. Object = { my. Method: function () { //DANGER console. log(this); } }; // this === window or global object my. Object. my. Method() const my. Method = my. Object. my. Method; // this === my. Object!!!!Ohno. XXX my. Object. my. Method() // this === window or global object my. Method() const my. Method = my. Object. my. Method; // this === window or global object my. Method()
Tips Comments in React To build static files: {/* This is a comment*/} npm run build 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 i. e. npm start From here, you can view files using your browser
The React way … Parent State update • event communicated using callback • props • callbacks In this way, a parent can apply higher level knowledge to update the behaviour of a child component Child event render Another child
Sample … class App extends React. Component{ constructor(props){ super(props); this. state = {button. Text: "default text"} } class XButton extends React. Component{ app. Handler = () => { this. set. State({button. Text: "Click me again!"}) } render() { return ( <div class. Name="App"> <XButton text={this. state. button. Text} colour="blue" c all. Parent={this. app. Handler}></XButton> </div> ); } } render(){ return ( <input type='button' value={this. props. text} style={{color: this. props. colour, width : 100, height: 100 }} on. Click={this. handler}></input> ) } } handler = () => { this. props. call. Parent(); }
CSS …. App-header 2 { CSS style <div class. Name="App"> background-color: #282 c 34; <div class. Name="App-header 2">React example</div> min-height: 10 vh; <XButton text={this. state. button. Text} colour="blue“ display: flex; flex-direction: column; align-items: center; call. Parent={this. app. Handler}></XButton> </div> justify-content: center; font-size: calc(10 px + 2 vmin); color: white; } You can also use React modules (ref: https: //www. w 3 schools. com/react_css. asp )
Full Stack Client Web pages/ React Python client You can’t do this!! GET POST … Web Server Flask API Endpoints SQL QUERY DB postgresql Data tables
React and REST (POST and GET example) do. Post = () => { fetch('/coursedata', { method: 'POST', body: JSON. stringify({ title: 'New title added' , body: 'New body added. Hello body. ' , user. Id: 2 }), headers: { "Contenttype": "application/json; charset=UTF-8" } }). then(response =>{ return response. json() }). then(json => { this. set. State({ user: json }); } ◦ fetch. Data = () => { //In package. json add "proxy": "http: //localhost: 5000" //This will allow redirect to REST api in Flask w/o CORS errors fetch('/getdata') //Or whatever your API endpoint is. then(response => response. json() )//The promise response. then (json. Output => //json. Output now has result { this. format. Data(json. Output); //Set the data so your component can use it in the page } ) } We use ‘fetch’ and ‘promises’ This allows async API calls, then handle the return data and process as needed
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-developertools/fmkadmapgofadopljbjfkapdkoienihi? hl=en
Demo Topics ● ● Components State Props JSX
- Slides: 25