Carlos Guedes - 2015/12/02
Sky Uk Limited (we are hiring!)
Toptal
Software Engineer
+10 year experience in Web
Former teacher at ISEL
Churn In the JavaScript World (Jul14)
* Thoughtworks' Technology Radar
JavaScript Settles to Merly Chaotic (Nov15)
Spread Operator and Rest Parameters
[1, 2, ...[3, 4, 5], 6, 7]
Arrow Functions
[1, 2].map(v => v * 2)
Assignment Destructuring let { id, title } = this.props.album
Template literals text = `Album ${title} contains ...`
Object literals let obj = { foo, [key]: value, fn() {} }
Classes
class Todo extends Component {
}
varlet const
Symbols const symbol = Symbol('some desc')
Iterators
Generators
Promises
Maps WeakMaps Sets WeakSets
Proxies
Reflection
Modules export const foo = 'bar' import { render } from 'react-dom'
every time data changes, UI is re-rendered*
const { Component } = React
class Click extends Component {
constructor() {
super()
this.state = { counter: 2 }
}
handleClick() {
this.setState({ counter: this.state.counter + 1 })
}
render() {
const { counter } = this.state
return (
<a onClick={_ => this.handleClick()}>
You have clicked <strong>{counter}</strong> times.
</a>
)
}
}
ReactDOM.render(
<Click />,
document.querySelector('#root')
)
React's key design decision is to make the API seem like it re-renders the whole app on every update.
renderA: <div style={{color: 'red'}} />
renderB: <div style={{fontWeight: 'bold'}} />
=> [removeStyle color], [addStyle font-weight 'bold']
heuristics
n = 100 1.000.000 10.000
class Todo extends React.Component {
static propType = {
text: React.PropTypes.string.isRequired,
completed: React.PropTypes.boolean,
onToggle: React.PropTypes.func
}
render() {
const { text, completed, onToggle } = this.props
return (
<li onClick={onToggle}
style={{
textDecoration: completed
? 'line-through'
: 'none'
}}
>
{text}
</li>
)
}
const Component = (props) => <ui />
React 0.14
const Todo = ({
text, completed,
onToggle,
}) => (
<li onClick={onToggle}
style={{
textDecoration: completed
? 'line-through'
: 'none'
}}
>
{text}
</li>
)
<Todo text='Hey'
completed={false}
onToggle={...} />
Where is stored the application state?
... all the "fluxes"
Flux architecture
They have got a lot of (recurring) problems in the past with bidirectional flow
by Dan Abramov
(gaearon)
by Facebook
$ npm install redux react-redux
state = f(state, action)
// Counter reducer
function counter(state = 0, action) {
switch(action.type) {
case 'INCREMENT_COUNTER':
return state + 1
case 'DECREMENT_COUNTER':
return state - 1
}
return state
}
const store = createStore(counter)
// Action dispatching and store state
const before = store.getState()
store.dispatch({ type: 'INCREMENT_COUNTER' })
const after = store.getState()
expect(after).toEquals(before + 1)
Counter
Todo
API Explorer
const { createStore } = Redux
function counter(state = 0, action) {
switch(action.type) {
case 'INCREMENT_COUNTER':
return state + 1
case 'DECREMENT_COUNTER':
return state - 1
}
return state
}
const store = createStore(counter)
store.dispatch({ type: 'INCREMENT_COUNTER' })
class App extends React.Component {
render() {
return (
<Counter value={store.getState()} />
)
}
}
const Counter = ({value}) => <div>Counter: {value}</div>
function render() {
ReactDOM.render(
<App />,
document.querySelector('#root')
)
}
render()
store.subscribe(render)
store.dispatch({ type: 'INCREMENT_COUNTER' })
store.dispatch({ type: 'INCREMENT_COUNTER' })
$ npm install react-router
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, Link } from 'react-router'
const App = React.createClass({/*...*/})
...
render((
<Router>
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="inbox" component={Inbox}>
{/* add some nested routes where we want the UI to nest */}
{/* render the stats page when at `/inbox` */}
<IndexRoute component={InboxStats}/>
{/* render the message component at /inbox/messages/123 */}
<Route path="messages/:id" component={Message} />
</Route>
</Route>
</Router>
), document.body)
import React from 'react'
import { Link } from 'react-router'
...
<div>
<h1>Messages</h1>
<div className="master">
<ul>
{this.props.messages.map(msg => (
<li key={msg.id}><Link to={`/inbox/messages/${msg.id}`}>{msg.subject}</Link></li>
))}
</ul>
</div>
</div>
react-router
$ npm install react-bootstrap
const NavDropdownExample = React.createClass({
handleSelect(event, selectedKey) {
event.preventDefault();
alert('selected ' + selectedKey);
},
render() {
return (
<Nav bsStyle="tabs" activeKey={1} onSelect={this.handleSelect}>
<NavItem eventKey={1} href="/home">NavItem 1 content</NavItem>
<NavItem eventKey={2} title="Item">NavItem 2 content</NavItem>
<NavItem eventKey={3} disabled>NavItem 3 content</NavItem>
<NavDropdown eventKey={4} title="Dropdown" id="nav-dropdown">
<MenuItem eventKey="4.1">Action</MenuItem>
<MenuItem eventKey="4.2">Another action</MenuItem>
<MenuItem divider />
<MenuItem eventKey="4.4">Separated link</MenuItem>
</NavDropdown>
</Nav>
);
}
});
ReactDOM.render(<NavDropdownExample />, mountNode);
React-Bootstrap is a library of reuseable front-end components. You'll get the look-and-feel of Twitter Bootstrap, but with much cleaner code, via Facebook's React.js framework.
const modalInstance = (
<div className="static-modal">
<Modal.Dialog>
<Modal.Header>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>
One fine body...
</Modal.Body>
<Modal.Footer>
<Button>Close</Button>
<Button bsStyle="primary">Save changes</Button>
</Modal.Footer>
</Modal.Dialog>
</div>
);
ReactDOM.render(modalInstance, mountNode);
react-bootstrap
"Learn once, write anywhere"
"Write once, run anywhere"
"Write once, run anywhere"
React Native is focused on changing the way view code is written. For the rest, we look to the web for universal standards and polyfill those APIs where appropriate.
reconciliation
batch updates
async and native updates
60 fps