Cem Turan
Writing native Mobile Apps in Javascript
How to enable a web like workflow on native without sacrificing performance and feel.
and 💰💰💰
We're hiring!
They are hiring!
EVERYONE IS HIRING!
Facebook shift to mobile was good in term of business, but so damaging in term of engineering velocity because of three things:
- Mark Zuckerberg
- Christopher Chedeau (@vjeux)
... the same set of engineers should be able to build applications for whatever platform they choose, without needing to learn a fundamentally different set of technologies for each.
We call this approach "learn once, write anywhere"
- Tom Occhino
structure your organization around product teams
instead of
technical knowledge silos
building
F5 on web
How do we get there?
well with React... (SPOILER ALERT!)
+
var numbers = [1,2,3,4,5]
var doubled = []
for(var i = 0; i < numbers.length; i++) {
var newNumber = numbers[i] * 2
doubled.push(newNumber)
}
console.log(doubled) //=> [2,4,6,8,10]
var numbers = [1,2,3,4,5]
var doubled = numbers.map(n => n * 2)
console.log(doubled) //=> [2,4,6,8,10]
loggedInTv = (TextView) findViewById(R.id.login_tv);
loggedInTv.setText( isLoggedIn
? "Logged in as: " + model.name
: "Please log in"
);
loginBtn = (Button) findViewById(R.id.login_btn);
loginBtn.setVisibility( isLoggedIn
? View.GONE
: View.VISIBLE
);
//View construction / XML not included!!!
<View> //JSX syntax: Embedded DSL/Syntactic Sugar
<Text> {
isLoggedIn
? "Logged in as: " + model.name
: "Please log in"
}</Text>
{ isLoggedIn
? <LoginButton />
: null
}
</View>
How vs What
Shout out to FP!
JSX
Controllers
Models
Views
Templates
View Models
Primitive
Essentially state machines
Encapsulated and Reusable, components makes code reuse, testing and separation of concerns a breeze.
class ChatApp extends React.Component{
constructor(props){
super(props)
this.state = {
friends: [],
messages: []
}
// perform request for data
}
handleSubmit(message){
//...
}
render(){ return
<View>
<FriendList
friends={this.state.friends}/>
<MessageList
messages={this.state.messages}/>
<MessageInput
handleSubmit={m => this.handleSubmit(m)}/>
</View>
}
}
let MessageList = (props) =>
<View>
<Text>Messages:</Text>
{
props.messages.map(message =>{
return <MessageListItem
key={message.id}
message={message}
/>
})
}
</View>
//Available in React but coming very soon
//to React Native
Pure function
class ChatApp extends React.Component{
constructor(props){
super(props)
this.state = {
friends: [],
messages: []
}
// perform request for data
}
handleSubmit(message){
this.setState({
messages: messages.concat(message)
})
}
render(){ return
<View>
<FriendList
friends={this.state.friends}/>
<MessageList
messages={this.state.messages}/>
<MessageInput
handleSubmit={m => this.handleSubmit(m)}/>
</View>
}
}
class ChatApp extends React.Component{
constructor(props){
super(props)
this.state = {
friends: [],
messages: []
}
// perform request for data
}
handleSubmit(message){
// setState / server call / dispatch action
}
render(){ return
<View>
<FriendList
friends={this.state.friends}/>
<MessageList
messages={this.state.messages}/>
<MessageInput
handleSubmit={m => this.handleSubmit(m)}/>
</View>
}
}
Props
State
unidirectional flow: props down, events up
architectures: flux, cyclejs, elm-architecture
React Web | React Native | Android | iOS | |
---|---|---|---|---|
Block | <div> | <View> | <ViewGroup> | UIView |
Inline | <span> | <Text> | <TextView> | TextView |
Image | <img> | <Image> | <ImageView> | UIImageView |
Platform Dependent (suffixed)
Platform independent
Touchable (behavioral) components
Apple Watch?
What could possibly go wrong!?
Efficient because on every update:
Two-threaded architecture
Bridge ensures Async serialized communication.
Task queue of changes are transformed to Imperative native calls on the native side.
websocket
<View style={styles.row}>
<Image src={ /* ... */ } />
<View style={styles.textContainer}>
<Text style={styles.movieTitle} /* ... */ </Text>
<Text style={styles.movieYear} /* ... */ </Text>
</View>
</View>
var styles = {
row: {
backgroundColor: 'white',
alignItems: 'center',
flexDirection: 'row',
padding: 6
}
}
Learn flexbox.io
{ margin: 20, borderBottonWidth: 2, flex: 1, alignContent: 'center' }
{ left: 120, top: 220, width: 60, height: 60 }
Flexbox
Coordinates
import React, {Board, Led} from 'react-hardware';
const HIGH = 255, LOW = 0;
class FlashingLed extends React.Component {
constructor(props) {
super(props);
this.state = {
value: 0,
_timer: null,
};
}
componentDidMount() {
this.state._timer = setInterval(_ => (
this.setState({value: this.state.value === HIGH ? LOW : HIGH})
), this.props.interval);
}
render() {
return (
<Led {...this.props} value={this.state.value} />
);
}
}
class Application extends React.Component {
render() {
return (
<Board>
<FlashingLed pin={9} />
<FlashingLed pin={10} />
<FlashingLed pin={11} />
<FlashingLed pin={12} />
</Board>
);
}
}
var PORT = '/dev/tty.usbmodem1411';
React.render(<Application />, PORT);
HUGE!
reactiflux.slack.com
join.reactiflux.com (Discord)
Directory of React Native and React Web components and modules.
Clojurescript
Typescript
Kotlin
Dart
Elm
Cem Turan