layout:true class: middle, left
--- # Front-end frameworks .subheading[Component-based development] --- layout:true
--- ## Building UIs is hard !
--- ## You need an abstraction .bigger[ - To manage your state - To be more productive - To hide complexity - to scale - to do more ! ] --- ## How to choose a Framework ?
.footnote[https://github.com/gothinkster/realworld] --- ## How to choose a Framework ? .bigger[ Things to consider - ecosystem - learning curve - performance - taste ] --- ## Meet AngularJS Hey I'm angularJS. Nobody wants to use me anymore — except existing large projects that are waiting for migration. So make sure you meet my brother Angular 2. I introduced a lot of confusing concepts for beginners... - Dependency injection - Services, Factories, Providers - etc.. Things I accomplished really well... - Controllers - Template syntax (Directives) Good bye ! Angularjs --- ## Meet AngularJS
--- ## Meet React Hi, I'm React I'll help you build complex interactive user interfaces. I'm more a component-based **library** than a framework. This means that you can build your app the way you like. Build your views in a declarative way and let me do the rest. I really, really like **Javascript** and I hope you feel the same way ! Cheers, React --- ## Meet React
--- ## Meet Angular 2+ Hello, I'm Angular 2 I'm a component-base **framework**. I do things differently compared with React — Instead of letting you mess up with your codebase when having too much freedom, I enforce a specific code structure. You won't get lost in the javascript eco-system because I'll give you all tools you need (Routing, Data fetching, Forms, etc...) and teach you how to use them. I'm serious about code quality and robustness. Thank God for such a beautiful language: **Typescript**! Best regards, Angular 2 --- ## Meet Vue.js Hi, I'm Vue I'm a javascript library for building user interfaces. Combined with some other tools, I become a framework. You might be like: *“Come on ! Yet another Javascript framework”*. But I swear you won't be disappointed ! I've been learning from mistakes and success of others (especially React and Angular). Now, [I'm Harder, Better, Faster, Stronger](https://genius.com/Daft-punk-harder-better-faster-stronger-lyrics) --- ## Meet Vue.js
--- exclude: true ## Why React ? - ~~Separation of technologies~~ - Separation of concerns - Declarative user interfaces --- name: get-started-react ## Get started with React First, create a component – It can be an ES6 `class` or a `function` like below. ```js import React from 'react' import ReactDOM from 'react-dom' function App() { return (
You think it's HTML ?
No, It's Javascript
); } ``` Then attach your component to a DOM node ```js const rootElement = document.getElementById("root"); ReactDOM.render(
, rootElement); ``` [](https://codesandbox.io/s/lpjy6qr17) --- layout:true
.breadcrumbs[[Get started with React](#get-started-react)] --- ### Only Javascript Use JSX to describe your interface ```js function App() { return (
You think it's HTML ?
No, It's Javascript
) } ``` JSX expressions become regular JavaScript function calls and evaluate to JavaScript objects. ```js const e = React.createElement function App() { return e('div', { className: "App" }, e('h1', null, "You think it's HTML ?"), e('p', null, "No, It's Javascript"), ) } ``` --- ### Embedding Expressions in JSX You can put any valid [Javascript expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Expressions) inside the **curly braces** in JSX. Because JSX is just Javascript ```js const name = 'Paul Nta'; *const element =
Hello, {name}
; ReactDOM.render( element, document.getElementById('root') ); ``` --- ### Embedding Expressions in JSX JSX expression are **function calls** that return objects — we call them "Elements" ```js const element = React.createElement( 'h1', { className: 'greeting' }, 'Hello, Paul Nta' ); ``` ```js // Note: this structure is simplified const element = { type: 'h1', props: { className: 'greeting', children: 'Hello, Nta!' } }; ``` --- ### Embedding Expressions in JSX ```js function formatName(user) { return user.firstName + ' ' + user.lastName; } const user = { firstName: 'Paul', lastName: 'Nta' }; const element = (
Hello, {formatName(user)}!
); ReactDOM.render( element, document.getElementById('root') ); ``` --- ### JSX is an Expression You can use JSX inside of `if` statements and `for` loops, assign it to variables, accept it as arguments, and return it from functions: ```js function getGreeting(user) { if (user) { return
Hello, {formatName(user)}!
; } return
Hello, Stranger.
; } ``` --- ### Attributes with JSX Use quotes to pass string literals as attributes ```js const element =
; ``` Use curly braces to embed a JavaScript expression in an attribute ```js const element =
; ``` > **Warning:** Since JSX is closer to JavaScript than to HTML, React DOM uses camelCase property naming convention instead of HTML attribute names. For example, `class` becomes `className` in JSX, and `tabindex` becomes `tabIndex`. --- ### Components and Props Components let you split the UI into independent, reusable pieces, and think about each piece in isolation.
.footnote[https://bitsrc.io/] --- ### Components and Props The simplest way to define a component is to write a JavaScript function ```js function Welcome(props) { return
Hello, {props.name}
; } ``` You can also use an ES6 class to define a component. Classes have some additional features that we will discuss later ```js class Welcome extends React.Component { render() { return
Hello, {this.props.name}
; } } ``` Use it like this ```js const element =
``` --- ### Component State State is similar to props, but it is private and fully controlled by the component. Components defined as a class can have a locale state ```js class TodoApp extends React.Component { constructor(props) { super(props) this.state = { items: [ { id: 0, text: "Learn JavaScript", done: false }, { id: 1, text: "Learn React", done: false }, { id: 2, text: "Build something awesome", done: true } ] } } render() { return (
{this.state.items.length} todos
) } } ``` --- ### Component State ```js class TodoApp extends React.Component { /*...*/ render() { const { items } = this.state return (
Todos:
{items.map(item => (
{item.text}
))}
) } } ``` [](https://codesandbox.io/s/5x60yll8lp) --- ### Updating Component State .smaller[ **Do Not Modify State Directly.** The only way to update a component's state is to use `this.setState()`. This will not re-render a component ```js // Wrong this.state.items = [] this.state.items.push({ text: '...'}) ``` Instead use `setState(obj)` or `setState(function)` ```js // Correct this.setState({ items: [] }) this.setState((state, props) => ({ items: [...state.items, newItem] })) ``` ] --- ### Immutability In React, `this.state` is treated as if it were immutable. When you update a part of the state, it must have a new reference. A solution is to create copies of the objects in this.state and manipulate the copies, assigning them back using setState() ```js const items = ['Angular', 'Vue'] const updatedItems = items; updatedItems.push('React'); items === updatedItems // true ! this.setState({ items: updatedItems }) ``` --- ### Updating Component State ```js class TodoApp extends React.Component { constructor(props) { super(props); this.state = { items: [/*...*/] }; } * handleRemove = (id) => { * const { items } = this.state * this.setState({ * items: items.filter(item => item.id !== id) * }) * } render() {/*...*/} } ``` --- ### Handling Events ```js // class TodoApp.render() {items.map(item => ( /*...*/ *
this.handleRemove(item.id)}> /*...*/ ))} ``` [](https://codesandbox.io/s/oqo163on35) - React events are named using camelCase, rather than lowercase - With JSX you pass a function as the event handler - React normalizes events so that they have consistent properties across different browsers. See [supported events](https://reactjs.org/docs/events.html#supported-events) --- ### Composing components ```js // components/TodoItem.js import React from "react"; function TodoItem(props) { const { id, text, done, onRemove } = props; const className = done ? "done" : ""; return (
{text}
X
); } export default TodoItem; ``` --- ### Composing components ```js // index.js class TodoApp extends React.Component { /*...*/ render() { return (
Todos:
{this.state.items.map(item => ( *
this.handleRemove(item.id)} * /> ))}
); } } ``` [](https://codesandbox.io/s/k1555wr2v) --- ### Containment Some components don’t know their children ahead of time. This is especially common for components like Sidebar, Dialog or Layout that represent generic “boxes”. For this, you have access to a special prop called `children`. ```js function Layout(props) { return (
{props.title}
* {props.children}
); } ``` ```html
* The content
``` .footnote[Read more: https://reactjs.org/docs/composition-vs-inheritance.html] --- ### Containment example .smaller[ Here is an example of how we can use the `Layout` component we defined earlier for to wrap our todo list. ```js // index.js class TodoApp extends React.Component { /*...*/ render() { return ( *
{this.state.items.map(item => (
this.handleRemove(item.id)} /> ))}
*
); } } ``` ] [](https://codesandbox.io/s/mjw4jlr169) --- exclude: true ### Concepts you should understand - Method binding - Lists and keys - Deal with immutability --- ### Method binding ```js class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; // This binding is necessary // to make `this` work in the callback * this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(state => ({ isToggleOn: !state.isToggleOn })); } render() { return ( *
{this.state.isToggleOn ? 'ON' : 'OFF'}
); } } ``` --- ### Method binding alternative #1 ```js class LoggingButton extends React.Component { // This syntax ensures `this` is bound within handleClick. // Warning: this is *experimental* syntax. handleClick = () => { console.log('this is:', this); } render() { return (
Click me
); } } ``` --- ### Method binding alternative #2 ```js class LoggingButton extends React.Component { handleClick() { console.log('this is:', this); } render() { // This syntax ensures `this` is bound within handleClick return ( *
this.handleClick(e)}> Click me
); } } ``` > The problem with this syntax is that a different callback is created each time the `LoggingButton` renders. --- ### Method binding explained ```js class Foo { constructor(name){ this.name = name } display() { console.log(this.name); } } const foo = new Foo('paulnta'); foo.display(); // paulnta ``` The assignment operation below simulates loss of context similar to passing a handler as a callback in a React Component ```js const display = foo.display; display(); // TypeError: this is undefined ``` .footnote[[This is why we need to bind event handlers in Class Components in React](https://medium.freecodecamp.org/this-is-why-we-need-to-bind-event-handlers-in-class-components-in-react-f7ea1a6f93eb)] --- ### Lists and keys > Keys should be given to the elements inside the array to give the elements a stable identity ```js function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => *
{number}
); return (
{listItems}
); } const numbers = [1, 2, 3, 4, 5] const element =
``` - keys Must Only Be **Unique** Among **Siblings** - avoid using array indexes as key. [Why?](https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318) --- ### References - [React main concepts](https://reactjs.org/docs/hello-world.html) — Read more about main concepts - [create-react-app](https://facebook.github.io/create-react-app/) — the easiest way to get started with React - [React router](https://reacttraining.com/react-router/web/guides/quick-start) - Declarative routing for React