Thinking in REACT
What?
A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES
JUst the V in MVC: React makes no assumptions about the rest of your technology stack
one-way reactive data flow
Reusable UI components FTW
Hello World!
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
A word about JSX
JavaScript syntax extension that looks similar to XML
REACT JSX TRANSFORM
XML like syntax -> Plain Javascript
// JSX
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
// PLAIN JAVASCRIPT TRANSFORMED
ReactDOM.render(React.createElement(
'h1',
null,
'Hello, world!'
), document.getElementById('example'));
Attribute Expressions
var person = <Person
name={window.isLoggedIn ? window.name : ''}
/>;
Attributes
var input = <input type="button" disabled={true} />;
var abs_shape = <div style={{
position: "absolute",
width: "100%",
height: "100%",
backgroundColor: this.state.beverage.color,
}}>;
Child Expressions
var content = <Container>
{window.isLoggedIn ? <Nav /> : <Login />}
</Container>;
A more complex component
Introducing React classes
var React = require('react');
var ReactDOM = require('react-dom');
var MyComponent = React.createClass({
render: function(){
return (
<h1>Hello, world! I am a new Component!</h1>
);
}
});
ReactDOM.render(
<MyComponent/>,
document.getElementById('example')
);
With ES2015
import React from 'react';
class MyComponent extends React.Component {
render() {
return (
<h1>Hello, world! I am a new Component!</h1>
);
}
}
ReactDOM.render(
<MyComponent/>,
document.getElementById('example')
);
Lifecycle
componentWillMount – Invoked once before rendering occurs
componentDidMount – Invoked once, after rendering occurs
shouldComponentUpdate – Return value determines whether component should update
componentWillUnmount – Invoked prior to unmounting component
SPECS
getInitialState – Return value is the initial value for state
getDefaultProps – Sets fallback props values if props aren’t supplied
mixins – An array of objects, used to extend the current component’s functionality
The State
class BeerBox extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
abv: 0,
origin: '',
ok: false
};
}
loadBeerFromServer() {
setTimeout(() => {
this.setState(
{
name: 'Guinness',
abv: 5,
origin: 'Ireland',
ok: true
}
);
}, 2000);
}
componentDidMount() {
this.loadBeerFromServer();
}
//...
};
MIXINS
var SetIntervalMixin = {
componentWillMount: function() {
this.intervals = [];
},
setInterval: function() {
this.intervals.push(setInterval.apply(null, arguments));
},
componentWillUnmount: function() {
this.intervals.forEach(clearInterval);
}
};
var TickTock = React.createClass({
mixins: [SetIntervalMixin], // Use the mixin
getInitialState: function() {
return {seconds: 0};
},
componentDidMount: function() {
this.setInterval(this.tick, 1000);
},
tick: function() {
this.setState({seconds: this.state.seconds + 1});
},
render: function() {
return (
<p>
React has been running {this.state.seconds} s.
</p>
);
}
});
LIVE DEMO!
https://github.com/DjangoBeer/reactjs-samples/tree/master/lifecycle
Thinking in React
SearchBar
BeerTable
BeerRow
BeerOriginRow
BeerSearchBox
Start From the smaller components
import React from 'react';
class BeerOriginRow extends React.Component {
render() {
return (
<tr><th colSpan="2">{this.props.origin}</th></tr>
);
}
};
export default BeerOriginRow;
import React from 'react';
class BeerRow extends React.Component {
render() {
return (
<tr>
<td>{this.props.beer.name}</td>
<td>{this.props.beer.abv}%</td>
</tr>
);
}
};
export default BeerRow;
Who uses these components?
class BeerTable extends React.Component {
render() {
var rows = [];
var lastOrigin = null;
this.props.beers.forEach(beer => {
if (beer.name.toLowerCase()
.indexOf(this.props.filterText.toLowerCase()) === -1) {
return;
}
if (beer.origin !== lastOrigin) {
rows.push(
<BeerOriginRow origin={beer.origin} key={beer.origin} />
);
}
rows.push(<BeerRow beer={beer} key={beer.name} />);
lastOrigin = beer.origin;
});
return (
<table>
//...
<tbody>{rows}</tbody>
</table>
);
}
};
BeerTable receives a list of beers and a query, then it renders everything
We need a SearchBox able to trigger an event on text change! Pass it a callback!
class SearchBar extends React.Component {
handleChange() {
this.props.onUserInput(
React.findDOMNode(this.refs.filterTextInput).value
);
}
render() {
return (
<form>
<input
type="text"
placeholder="Search..."
value={this.props.filterText}
ref="filterTextInput"
onChange={this.handleChange.bind(this)} />
</form>
);
}
};
export default SearchBar;
Put it all Together!
class BeerSearchBox extends React.Component {
// ....
handleUserInput (filterText) {
this.setState({
filterText: filterText,
});
}
render() {
return (
<div>
<SearchBar onUserInput={this.handleUserInput.bind(this)}/>
<BeerTable filterText={this.state.filterText} beers={this.state.beers}/>
</div>
)
}
};
Live DEMO!!!
https://github.com/DjangoBeer/reactjs-samples/tree/master/beersearch
A word about Touchstone.js
Live DEMO!!!
https://github.com/astagi/cincin
More in REACT.js World
Server-side RENDERING
Faster Page LOADS
By rendering on the server, you get to send down a complete webpage, cut out an HTTP request
More reliable SEO
Any crawler that navigates to your site will see a complete page filled with content, rather than an empty page that requires JavaScript execution.
Flux
Flux is an architecture that Facebook uses internally when working with React. It is not a framework or a library. It is simply a new kind of architecture that complements React and the concept of Unidirectional Data Flow.
React Native
// iOS
var React = require('react-native');
var { TabBarIOS, NavigatorIOS } = React;
var App = React.createClass({
render: function() {
return (
<TabBarIOS>
<TabBarIOS.Item title="React Native" selected={true}>
<NavigatorIOS initialRoute={{ title: 'React Native' }} />
</TabBarIOS.Item>
</TabBarIOS>
);
},
});
// Android
var React = require('react-native');
var { DrawerLayoutAndroid, ProgressBarAndroid } = React;
var App = React.createClass({
render: function() {
return (
<DrawerLayoutAndroid
renderNavigationView={() => <Text>React Native</Text>}>
<ProgressBarAndroid />
</DrawerLayoutAndroid>
);
},
});
Conclusions
EMAil: a.stagi@nephila.it
Twitter: @4stagi
Github: @astagi
Thinking in React
By Andrea Stagi
Thinking in React
My dip into the React.js world
- 2,383