Slide 1

Slide 1 text

REACT IN 50 MINUTES #reactin50mins Maarten Mulders (@mthmulders)

Slide 2

Slide 2 text

ABOUT ME @mthmulders @Java_Champions @OracleACE @InfoSupportBV #reactin50mins Maarten Mulders (@mthmulders)

Slide 3

Slide 3 text

REACT... “ React is a library for declaratively building user interfaces using JavaScript and (optionally) XML. #reactin50mins Maarten Mulders (@mthmulders)

Slide 4

Slide 4 text

REACT VS. OTHERS No two-way data binding No templating language Just user interface (no routing, no HTTP client) Plain JavaScript (or add JSX, TypeScript, ...) Virtual DOM vs. actual DOM #reactin50mins Maarten Mulders (@mthmulders)

Slide 5

Slide 5 text

MODERN JAVASCRIPT #reactin50mins Maarten Mulders (@mthmulders)

Slide 6

Slide 6 text

CLASSES class Amount { constructor(currency, value) { this.currency = currency; this.value = value; } getCurrency() { return this.currency; } } const text = new Amount('EUR', 15).getCurrency(); document.getElementById('app').innerText = text; 1 2 3 4 5 6 7 8 9 10 11 12 13 EUR #reactin50mins Maarten Mulders (@mthmulders)

Slide 7

Slide 7 text

FUNCTIONS function isEven(number) { return number % 2 == 0; } const text = isEven(42) document.getElementById('app').innerText = text; 1 2 3 4 5 6 true #reactin50mins Maarten Mulders (@mthmulders)

Slide 8

Slide 8 text

ARROW FUNCTIONS const isEven = (number) => { return number % 2 == 0; } const text = isEven(42) document.getElementById('app').innerText = text; 1 2 3 4 5 6 true #reactin50mins Maarten Mulders (@mthmulders)

Slide 9

Slide 9 text

OBJECT DECOMPOSITION const person = { name : 'Jane Doe', age: 42, occupancy: 'JavaScript dev' }; const { name, age } = person; const text = age document.getElementById('app').innerText = text; 1 2 3 4 5 42 #reactin50mins Maarten Mulders (@mthmulders)

Slide 10

Slide 10 text

ARRAY DECOMPOSITION const numbers = [ 'one', 'two', 'three' ]; const [ first, second ] = numbers; const text = second document.getElementById('app').innerText = text; 1 2 3 4 5 two #reactin50mins Maarten Mulders (@mthmulders)

Slide 11

Slide 11 text

OBJECT SHORTHAND NOTATION const name = 'Jane Doe'; const age = 42; const person = { name, age }; const text = JSON.stringify(person) document.getElementById('app').innerText = text; 1 2 3 4 5 6 {"name":"Jane Doe","age":42} #reactin50mins Maarten Mulders (@mthmulders)

Slide 12

Slide 12 text

STRING INTERPOLATION class Amount { constructor(currency, value) { this.currency = currency; this.value = value; } toString() { return `${this.currency} - ${this.value}`; } } const text = new Amount('EUR', 150).toString(); document.getElementById('app').innerText = text; 1 2 3 4 5 6 7 8 9 10 11 12 13 EUR - 150 #reactin50mins Maarten Mulders (@mthmulders)

Slide 13

Slide 13 text

BASIC JSX #reactin50mins Maarten Mulders (@mthmulders)

Slide 14

Slide 14 text

WHAT IS JSX? A syntax extension to JavaScript real XML, not a string of characters allows embedded expressions supports attributes Can be nested Automatic XSS prevention But it has its limitations Needs to be transpiled to JavaScript e.g. React.createElement(...) #reactin50mins Maarten Mulders (@mthmulders)

Slide 15

Slide 15 text

ELEMENTS Elements can be regular DOM elements... (for now, but not for long) const element =
Hello, world
ReactDOM.render(element, document.getElementById('app')); 1 2 Hello, world #reactin50mins Maarten Mulders (@mthmulders)

Slide 16

Slide 16 text

ATTRIBUTES Elements can have attributes, but they can have different names than HTML attributes: const element =
I'm blue
ReactDOM.render(element, document.getElementById('app')); 1 2 I'm blue #reactin50mins Maarten Mulders (@mthmulders)

Slide 17

Slide 17 text

... and they can behave differently: const style = { color: 'red', fontWeight: 'bold' }; const element =
I'm blue
ReactDOM.render(element, document.getElementById('app')); 1 2 3 I'm blue #reactin50mins Maarten Mulders (@mthmulders)

Slide 18

Slide 18 text

SINGLE ROOT NODE Values must have a single root node (or an array) const element = [
x
,
y
] ReactDOM.render(element, document.getElementById('app')); 1 2 3 x y #reactin50mins Maarten Mulders (@mthmulders)

Slide 19

Slide 19 text

COMPONENTS Function that returns a React element. const Greeter = (props) =>
Hello, world!
ReactDOM.render(, document.getElementById('app')); 1 2 Hello, world! #reactin50mins Maarten Mulders (@mthmulders)

Slide 20

Slide 20 text

ADVANCED JSX #reactin50mins Maarten Mulders (@mthmulders)

Slide 21

Slide 21 text

EXPRESSIONS IN JSX const answerToQuestionOfLife = 40 + 2; const askQuestionOfLife = () => answerToQuestionOfLife; const Example = () =>
The answer to the ultimate question of life, universe and everything: { askQuestionOfLife() }
; ReactDOM.render(, document.getElementById('app')); 1 2 3 4 5 6 7 8 The answer to the ultimate question of life, universe and everything: 42 #reactin50mins Maarten Mulders (@mthmulders)

Slide 22

Slide 22 text

OR USE YOUR PROPS / ARGUMENTS! const Greeter = (props) =>
Hello { props.name }!
ReactDOM.render(, document.getElementById('app')); 1 2 Hello Dublin! #reactin50mins Maarten Mulders (@mthmulders)

Slide 23

Slide 23 text

OR USE YOUR PROPS / ARGUMENTS! Alternatively, using object decomposition: const Greeter = ({ name }) =>
Hello { name }!
ReactDOM.render(, document.getElementById('app')); 1 2 Hello Dublin! #reactin50mins Maarten Mulders (@mthmulders)

Slide 24

Slide 24 text

CONTROL STATEMENTS INSIDE JSX const ClapHands = () => Clapping hands...; const DryTears = () => Drying tears...; const ShowEmotion = ({ happy }) => happy ? : ; ReactDOM.render(, document.getElementById('app')); 1 2 3 4 5 6 7 Clapping hands... #reactin50mins Maarten Mulders (@mthmulders)

Slide 25

Slide 25 text

CONTROL STATEMENTS INSIDE JSX (2) const Ticker = ({ symbol }) =>
{ symbol }
; const TickerList = ({ symbols }) => symbols.map( (symbol) => ); const symbols = ['HEIA', 'PHIA']; ReactDOM.render(, document.getElementById('app')); 1 2 3 4 5 6 7 8 9 HEIA PHIA #reactin50mins Maarten Mulders (@mthmulders)

Slide 26

Slide 26 text

REACT "MAGIC" #reactin50mins Maarten Mulders (@mthmulders)

Slide 27

Slide 27 text

AT BUILD TIME So far, we've written components and wired them together. Babel or tsc transpiles them to React.createElement(...) invocations: /** transpiles into */ React.createElement(Greeter, { name: 'World' }, null) #reactin50mins Maarten Mulders (@mthmulders)

Slide 28

Slide 28 text

AT RUN TIME The React.createElement invocations form a tree of components. React maintains a virtual DOM based on your component tree. The virtual DOM is compared to the actual DOM. Only necessary changes are executed. #reactin50mins Maarten Mulders (@mthmulders)

Slide 29

Slide 29 text

RECONCILIATION React syncs the virtual and the actual DOM based on two assumptions: 1. If two elements are of different type, the (sub) tree will be different. 2. The key prop identifies child elements over re-renders. This tells React what makes two elements "the same". #reactin50mins Maarten Mulders (@mthmulders)

Slide 30

Slide 30 text

1. ELEMENTS OF DIFFERENT TYPE const DutchGreeter = ({ name }) =>
🇳🇱 Hallo, { name }!
; const EnglishGreeter = ({ name }) =>
🇬🇧 Hello, { name }!
; const IrishGreeter = ({ name }) =>
🇮🇪 Dhuit, { name }!
; const App = ({ lang, name }) => { switch(lang) { case 'ie': return case 'nl': return case 'en': default : return } }; ReactDOM.render(, document.getElementById('app')); 1 2 3 4 5 6 7 8 9 10 11 12 13 🇳🇱 Hallo, Dublin! #reactin50mins Maarten Mulders (@mthmulders)

Slide 31

Slide 31 text

2. THE key PROP const randomPrice = () => 100 + Math.floor(Math.random() * 900) const Ticker = ({ symbol }) => { symbol }: { randomPrice() } — ; const symbols = ['HEIA', 'PHIA', 'ASML', 'KLMR'].map( (symbol) => ); ReactDOM.render(, document.getElementById('app')); 1 2 3 4 5 6 7 8 9 #reactin50mins Maarten Mulders (@mthmulders)

Slide 32

Slide 32 text

YOUR ENVIRONMENT 1. Keeping state 2. Reacting to events 3. Fetching data over HTTP 4. Storing data #reactin50mins Maarten Mulders (@mthmulders)

Slide 33

Slide 33 text

LOCAL STATE INSIDE A COMPONENT const Counter = () => { const [ counter, setCounter ] = React.useState(0); return
Counter: { counter }
} ReactDOM.render(, document.getElementById('app')); 1 2 3 4 5 6 7 Counter: 0 #reactin50mins Maarten Mulders (@mthmulders)

Slide 34

Slide 34 text

REACTING TO EVENTS Similar to DOM event handling, but 1. event names are different: onClick vs onclick. 2. event handlers are always functions, never strings. 3. event handlers are bound to a component, should not live globally. 4. event handlers receive an synthetic event - browser-agnostic! #reactin50mins Maarten Mulders (@mthmulders)

Slide 35

Slide 35 text

CLICK CALLBACKS const Counter = () => { const [ counter, setCounter ] = React.useState(0); const increase = () => setCounter(counter + 1); const decrease = () => setCounter(counter - 1); return
Counter: { counter }
+   -
} ReactDOM.render(, document.getElementById('app')); 1 2 3 4 5 6 7 8 9 10 11 12 Counter: 0 + - #reactin50mins Maarten Mulders (@mthmulders)

Slide 36

Slide 36 text

CHANGE CALLBACKS const Greeter = () => { const [ name, setName ] = React.useState(''); const updateName = (e) => setName(e.target.value); const callback = () => alert(`Hi ${name}`); return

Greet { name }!
} ReactDOM.render(, document.getElementById('app')); 1 2 3 4 5 6 7 8 9 10 Greet ! #reactin50mins Maarten Mulders (@mthmulders)

Slide 37

Slide 37 text

FETCHING DATA OVER HTTP What we need: 1. A bit of Plain Old JavaScript to fetch some data 2. A component to show the fetched data #reactin50mins Maarten Mulders (@mthmulders)

Slide 38

Slide 38 text

1. A DATA RETRIEVAL API const url = 'https://opendata.rdw.nl/resource/m9d7-ebf2.json'; const getCar = (licenseNumber) => { return fetch(url + '?kenteken=' + licenseNumber) }; #reactin50mins Maarten Mulders (@mthmulders)

Slide 39

Slide 39 text

1. A DATA RETRIEVAL API const checkStatus = (response) => { if (response.status >= 200 && response.status < 300) { return Promise.resolve(response); } else { return Promise.reject(`HTTP error ${response.status}: ${response.statusText}`); } }; const url = 'https://opendata.rdw.nl/resource/m9d7-ebf2.json'; const getCar = (licenseNumber) => { return fetch(url + '?kenteken=' + licenseNumber) .then(checkStatus) }; #reactin50mins Maarten Mulders (@mthmulders)

Slide 40

Slide 40 text

1. A DATA RETRIEVAL API const checkStatus = (response) => { if (response.status >= 200 && response.status < 300) { return Promise.resolve(response); } else { return Promise.reject(`HTTP error ${response.status}: ${response.statusText}`); } }; const parseJson = (response) => response.json(); const url = 'https://opendata.rdw.nl/resource/m9d7-ebf2.json'; const getCar = (licenseNumber) => { return fetch(url + '?kenteken=' + licenseNumber) .then(checkStatus) .then(parseJson) }; #reactin50mins Maarten Mulders (@mthmulders)

Slide 41

Slide 41 text

1. A DATA RETRIEVAL API const checkStatus = (response) => { if (response.status >= 200 && response.status < 300) { return Promise.resolve(response); } else { return Promise.reject(`HTTP error ${response.status}: ${response.statusText}`); } }; const parseJson = (response) => response.json(); const url = 'https://opendata.rdw.nl/resource/m9d7-ebf2.json'; const getCar = (licenseNumber) => { return fetch(url + '?kenteken=' + licenseNumber) .then(checkStatus) .then(parseJson) .then(response => `${response[0].merk} ${response[0].handelsbenaming}`); }; #reactin50mins Maarten Mulders (@mthmulders)

Slide 42

Slide 42 text

2. A COMPONENT TO SHOW THE FETCHED DATA const ShowCar = () => { const [ { car, loading }, setState ] = React.useState({ loading: true }); const fetchCarDetails = async (licenseNumber) => { const car = await getCar(licenseNumber); setState({loading: false, car}); } React.useEffect(() => { fetchCarDetails('33JFX4'); }, [ ]); return loading ?
Loading...
:
{ car }
; }; ReactDOM.render(, document.getElementById('app')); 1 2 3 4 5 6 7 8 9 10 11 12 13 OPEL ZAFIRA #reactin50mins Maarten Mulders (@mthmulders)

Slide 43

Slide 43 text

STORING DATA IN YOUR BROWSER Local Storage & Session Storage Part of the Stores and retrieves string values Serialise objects with JSON.stringify() Deserialise with JSON.parse() Persistent during browser session with sessionStorage over browser shutdowns with localStorage Web Storage API #reactin50mins Maarten Mulders (@mthmulders)

Slide 44

Slide 44 text

DELIVERING APPS 1. Debugging 2. Testing 3. Building #reactin50mins Maarten Mulders (@mthmulders)

Slide 45

Slide 45 text

DEBUGGING Install the React Developer Tools for your browser of choice. #reactin50mins Maarten Mulders (@mthmulders)

Slide 46

Slide 46 text

INSPECTING COMPONENT TREE #reactin50mins Maarten Mulders (@mthmulders)

Slide 47

Slide 47 text

DEBUGGING #reactin50mins Maarten Mulders (@mthmulders)

Slide 48

Slide 48 text

TESTING YOUR COMPONENTS Use Jest (test platform & library) and (React) Testing Library (testing utilities) Render a React component in a unit test Make assertions about its output and behaviour #reactin50mins Maarten Mulders (@mthmulders)

Slide 49

Slide 49 text

TESTING A SIMPLE COMPONENT import { render, screen } from '@testing-library/react' describe('', () => { it('should render text', () => { render(); expect(screen.getByText(/hello, Dublin/i)).toBeVisible(); }); }); #reactin50mins Maarten Mulders (@mthmulders)

Slide 50

Slide 50 text

TESTING BEHAVIOUR OF A COMPONENT import { fireEvent, render, screen } from '@testing-library/react' describe('', () => { it('should invoke action on click', () => { const callback = jest.mock(); render(); fireEvent.click(screen.getByRole('link')); expect(callback).toHaveBeenCalled(); }); }); #reactin50mins Maarten Mulders (@mthmulders)

Slide 51

Slide 51 text

DEVELOPING & SHIPPING AN APP tl;dr: use (CRA) Uses Webpack, Babel, ESLint and a dozen of other tools Tested to work together Live-reloading of changed code Source maps for easy debugging Have an ready-to-go app in one command Create React App npx create-react-app my-next-killer-app // or npm i -g create-react-app create-react-app my-next-killer-app #reactin50mins Maarten Mulders (@mthmulders)

Slide 52

Slide 52 text

USING CRA npm run start to start developing npm run build to create a production build npm run test to run unit tests #reactin50mins Maarten Mulders (@mthmulders)

Slide 53

Slide 53 text

TAKE AWAYS Use Create React App Think in (small) components Think declaratively #reactin50mins Maarten Mulders (@mthmulders)

Slide 54

Slide 54 text

THANK YOU! REFERENCES & MORE INFORMATION Create React App Philippe De Ryck on "Building Secure React Applications" @mthmulders #reactin50mins Maarten Mulders (@mthmulders)