Advanced Topics in Concurrency and Reactive Programming: React Majeed Kassis
What is React? React is “a library for creating user interfaces” Instead of building HTML templates, build components. React follows component oriented development paradigm The general idea is to break the UI into a set of components. Implement for each component a reusable react component Combine and nest components to create the complete UI. Benefits: Code (component) reuse. Better code readability – components are stored in their own classes Easily testable code - we can test each component dependently https://scrimba.com/casts/cast-264 class Main extends React.Component { render() { return ( <h1>Hello world!</h1> ); } ReactDOM.render(<Main />, document.getElementById('root'));
What does it mean? <html> <body> <div style="font-size: 24px"> <div> <h1>Mr Tiger </h1> <img src="http://lorempixel.com/output/animals-q-c-640-480-3.jpg" /> </div> <h3>My hobbies:</h3> <ul> <li>Eat</li> <li>Sleep</li> <li>Code</li> </ul> </body> </html>
How it is done? Each React component is defined as a javascript class The class extends React.Component class Each component is implemented and returned inside render() function. Example:
React – Building Blocks Components: The basic building block of React Can be created via: Implementing a class extending React.component and implementing render function. Using factory method: React.createClass() and implementing render function. Props: Each Component has a props object, to which we can add attributes. Accessing them is done using this.props React implements unidirectional data flow via props from parent to child When the properties change: ReactDOM.render(reactElement, domContainerNode) Is used to re-render the UI and keep it up to date.
React Data Flow: unidirectional data flow Data is sent from parent to child component They can be accessed using this.props in the child component Sent properties are immutable Component cannot change own properties! (only children) Example: “title” property is sent from HomePage to Header component.
Data flow example Modify HTML tag with new content every 2 seconds Each time taking a value from an Array randomly Storing the new value in the property ‘message’ of the parent And seeing React re-rendering the components to generate the up-to-date UI. Data: var messages = ['Hello, World', 'Hello, Planet', 'Hello, Universe']; Property: var randomMessage = messages[Math.floor((Math.random() * 3))]; Rendering function: ReactDOM.render( <Greeter message={randomMessage}/>, document.getElementById('root') ); https://scrimba.com/casts/cast-267 var Greeted = React.createClass({ render : function() { return ( <div>message received: {this.props.sentMessage}</div> ) } }); var Greeter = React.createClass({ render: function() { <div> <p>mesage sent: {this.props.message}</p> <Greeted sentMessage={this.props.message}/> </div> ); setInterval(function() { var messages = ['Hello, World', 'Hello, Planet', 'Hello, Universe']; var randomMessage = messages[Math.floor((Math.random() * 3))]; ReactDOM.render( <Greeter message={randomMessage}/>, document.getElementById('root') }, 2000); setInterval();
JSX – JavaScript eXtension JSX is a statically-typed, object-oriented programming language compiling to standalone JavaScript. Allows implementing UI elements in-lined in JS code JSX is a XML-like syntax extension to ECMAScript Allows (seamlessly) incorporating HTML syntax inside JS functions. JSX transforms from an XML-like syntax into native JavaScript XML elements are transformed into function calls XML attributes are transformed into objects JSX in depth: https://facebook.github.io/react/docs/jsx-in-depth.html JSX Tutorial: https://facebook.github.io/jsx/
React: JSX vs JS Syntax Any HTML syntax is converted to a function call of React.createElement
React Building Blocks State: Manipulation functions: Each React component has a state object. A state is used to store information(data) about the component that can change over time State in contrary to props cannot be altered by parent components. Only by current component. Manipulation functions: Accessed by this.state.variable Changed by this.setState({variable: value});
Props vs State props state Can get initial value from parent Component? Yes Can be changed by parent Component? No Can set default values inside Component? Can change inside Component? Can set initial value for child Components? Can change in child Components?
React Virtual DOM On every change React re-renders the page: Creates a new virtual DOM (in memory) ‘diff’s it with the previous version Computes minimal set of changes to apply on real DOM. Virtual DOM benefits: Avoids expensive DOM operations Minimizes access to the DOM Updates elements offline before modifying DOM Allows writing clean code that is not concerned with DOM changes.
From templated HTML to React components
First Step Take HTML code and move it into a React Component Move all properties inside {{ }} brackets class Main extends React.Component { render() { return ( <div style={{'font-size':'24px'}}> <div> <h1>Mr Tiger </h1> <img src="http://lorempixel.com/output/animals-q-c-640-480-3.jpg" /> </div> <h3>My hobbies:</h3> <ul> <li>Eat</li> <li>Sleep</li> <li>Code</li> </ul> ); } ReactDOM.render(<Main />, document.getElementById('root'));
Second step: move first div tag to own component Let’s create a class called “Person” and insert the HTML syntax inside its render function Defining “Person” class inheritably: defines a new tag named “Person” Allows us to pass new properties from parent to Person (child) via the new tag. New classes must be has their first letter capitalized “Person” and not “person”! class Person extends React.Component { render() { return ( <div> <h1>Mr Tiger </h1> <img src="http://lorempixel.com/output/animals-q-c-640-480-3.jpg" /> </div> ); } class Main extends React.Component { <div style={{'font-size':'24px'}}> <Person /> <h3>My hobbies:</h3> <ul> <li>Eat</li> <li>Sleep</li> <li>Code</li> </ul> ReactDOM.render(<Main />, document.getElementById('root'));
Third step: move 2nd div to its own component class Now we move the 2nd div block to a new class named “Hobbies” Instead of that block we add <Hobbies /> tag. class Person extends React.Component { render() { return ( <div> <h1>Mr Tiger </h1> <img src="http://lorempixel.com/output/animals-q-c-640-480-3.jpg" /> </div> ); } class Hobbies extends React.Component { <h3>My hobbies:</h3> <ul> <li>Eat</li> <li>Sleep</li> <li>Code</li> </ul> class Main extends React.Component { <div style={{'font-size':'24px'}}> <Person /> <Hobbies /> ReactDOM.render(<Main />, document.getElementById('root'));
4th step: let’s convert the list to JS We can use the powerful functional programming tools we learned to easily create lists without repeating code. use { variable } to evaluate the variable Otherwise it will be printed as is (text) to evaluate the function surround it with { } as well! Otherwise it will not be evaluated. class Person extends React.Component { render() { return ( <div> <h1>Mr Tiger </h1> <img src="http://lorempixel.com/output/animals-q-c-640-480-3.jpg" /> </div> ); } class Hobbies extends React.Component { var hobbies = ['Eat', 'Sleep', 'Code']; <h3>My hobbies:</h3> <ul> { hobbies.map((value, index) => { <li id={index}> {value} </li> }) </ul> class Main extends React.Component { <div style={{'font-size':'24px'}}> <Person /> <Hobbies /> ReactDOM.render(<Main />, document.getElementById('root'));
5th step: Let’s move this code to its own function! Increases readability Allows code reuse class Person extends React.Component { render() { return ( <div> <h1>Mr Tiger </h1> <img src="http://lorempixel.com/output/animals-q-c-640-480-3.jpg" /> </div> ); } function generateList(array){ <ul> { array.map((value, index) => { <li id={index}> {value} </li> }) </ul>); class Hobbies extends React.Component { var hobbies = ['Eat', 'Sleep', 'Code']; <h3>My hobbies:</h3> { generateList(hobbies) } class Main extends React.Component { <div style={{'font-size':'24px'}}> <Person /> <Hobbies /> ReactDOM.render(<Main />, document.getElementById('root'));
6th step: Let’s demonstrate props propagation from root node to child to grandchild Move data to their own dictionary: We propagate the DATA object by using tag properties: Person: Hobbies: Then update functions properly to use the new properties. const DATA = { name: 'Mr Tiger', imgURL: 'http://lorempixel.com/output/animals-q-c-640-480-3.jpg', hobbyList: ['Eat', 'Sleep', 'Code'] }; class Person extends React.Component { render() { return ( <div> <h1>{this.props.name} </h1> <img src={this.props.profileImage} /> </div> ); } function generateList(array){ <ul> { array.map((value, index) => { <li id={index}> {value} </li> }) </ul>); class Hobbies extends React.Component { <h3>My hobbies:</h3> { generateList(this.props.hobbyList) } class Main extends React.Component { <div style={{'font-size':'24px'}}> <Person name = {DATA.name} profileImage={DATA.imgURL}/> <Hobbies hobbyList = {DATA.hobbyList}/> ReactDOM.render(<Main />, document.getElementById('root'));
What did we learn? Splitting UI to reusable components Using helper functions to aid us in certain tasks As well as using variables and evaluating expressions Using Reacts unidirectional data flow to send values across components
Installing React Dependencies: Complete Guide: React: react, react-dom The React framework Babel: babel-core, babel-loader, babel-preset-react Used to convert JSX to plain JS Webpack: webpack, webpack-dev-server, html-webpack-plugin To convert React code to Javascript Complete Guide: https://www.codecademy.com/articles/react-setup-i