New variable types
let
const
var
NEVER
Sometimes
Always
// var declaration
function varTest() {
var x = 1
if (true) {
var x = 2 // same variable!
console.log(x) // 2
}
console.log(x) // 2
}
New variable types
// let declaration
function letTest() {
let x = 1
if (true) {
let x = 2 // different variable
console.log(x) // 2
}
console.log(x) // 1
}
var
let
const key = "mykey"
key = "newkey"
// error "key" is read only
New variable types -
const
const person = {
name: "Jennifer",
age: 43,
occupation: "Dentist",
}
person.name = "Jim"
New variable types -
const
{
"age": 43,
"name": "Jim",
"occupation": "Dentist"
}
➡
Arrow functions
ES5
ES6
var sayName =
function() {}
const sayName =
() => {}
() => {}
this
bound to global
const getFullName = (first, last) => {
return first + " " + last
}
Functions - implicit vs explicit return
var getFullName = function(first, last) {
return first + " " + last
}
ES5
ES6
const getFullName = (first, last) => first + " " + last
const getFullName = (first, last) =>
first + " " + last
explicit
implicit
explicit
ES6
const sayName = (name) => console.log("I am " + name + " !")
Arrow functions
Parameters
const sayName = name => console.log("I am " + name + " !")
const addThree = (a, b, c) => a + b + c
const abc = ["a", "b", "c"]
const def = ["d", "e", "f"]
const alpha = [ ...abc, ...def ]
["a", "b", "c", "d", "e", "f"]
Spread operator
Spread array
const basics = {firstName: "Frank", lastName: "von Hoven"}
const attributes = {job: "Software Engineer"}
const person = {...basics, ...attributes, eyes: "brown"}
{
firstName: "Frank",
lastName: "von Hoven",
job: "Software Engineer",
eyes: "brown"
}
Spread object
...
const name = person.name
const height = person.height
const location = person.location
console.log(name, height, location)
Object { destructuring }
ES5
const {
name,
height,
location,
sports
} = person
console.log(name, height, location)
ES6
const person = {
name: "Chris",
hairColor: "brown",
height: "6'1",
location: "Portland",
sports: ["football", "tennis"]
}
// "Chris", "6'1", "Portland"
https://github.com/lukehoban/es6features
JavaScript XML
This:
Compiles to:
<Text color="blue" >
Click Me
</Text>
React.createElement(
Text,
{color: "blue"},
"Click Me"
)
const MyComponent = <Text>Hello World</Text>
const MyImage = <Image source={someSource} style={styleObj} />
{ MyComponent }
{ MyImage }
const person = { name: "Chris", age: 22 }
const MyComponent = <Text>Hello { person.name }</Text>
const person = { name: "Chris", age: 22 }
const MyComponent = <Text>Hello { getName() }</Text>
const getName = () => person.name
const person = { name: "Chris", age: 22 }
if (person.age >= 20) {
return <Text>{person.name}</Text>
} else {
return <Text>Age is below 20</Text>
}
const person = { name: "Chris", age: 22 }
<Text>{person.name} {person.age > 20 ? "Is over 20" : "Is not over 20" }</Text>
ternary operator
<View>
<Text>Hello!</Text>
<Text>Good to see you here.</Text>
</View>
const greeting = (
<View>
<Text>Hello!</Text>
<Text>Good to see you here.</Text>
</View>
)
// in component
{ greeting }
tl;dr
View
ScrollView
Text
TextInput
Image
TouchableOpacity
HTML | React Native |
---|---|
<div> | <View> |
<p> | <Text> |
<input /> | <TextInput /> |
<button> | <TouchableOpacity /> |
class MyComponent extends React.Component {
render() {
return (
<Text>Hello World</Text>
)
}
}
class (stateful)
const MyComponent = () => (
<Text>Hello World</Text>
)
<MyComponent />
functional (stateless)
vs
Components ➡ React elements - what should appear on the screen.
Styles can be created one of three ways:
inline styles
<Text style={{color: "red"}}>Hello World</Text>
<View style={{width: 300}}>
style object
const styles = {
text: {
color: "red"
}
}
<Text style={styles.text}>Hello World</Text>
StyleSheet
import { StyleSheet, View, Text } from "react-native"
const styles = StyleSheet.create({
container: {
width: 300,
height: 130
},
text: {
color: "red"
}
})
<View style={styles.container}>
<Text style={styles.text}>Hello World</Text>
</View>
StyleSheet.create({...})
code
import React from "react"
import { Text } from "react-native"
class App extends React.Component {
state = { name: "Chris" }
// lifecycle methods
render() {
return (
<Text>{this.state.name}</Text>
)
}
}
class
<App />
import React from "react"
import { Text } from "react-native"
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
name: "Chris",
}
}
render() {
return(
<Text>{this.state.name}</Text>
)
}
}
Creating state
Using constructor to declare state
import React from "react"
import { View, Text } from "react-native"
class App extends React.Component {
state = { name: "Chris" }
updateName = () => {
this.setState({ name: "Amanda" })
}
render() {
return(
<View>
<Text onPress={this.updateName}>
{this.state.name}
</Text>
</View>
)
}
}
Updating state with
setState
Common props
value
placeholder
onChangeText
(val) => val: string
"string"
onSubmitEditing
"string"
() => {}
code
code
Can be assigned one of two ways:
ref="myComponent"
ref={(ref) => this.myComponent = ref}
code
render() {
const data = [
{ key: "Chris" },
{ key: "Amanda" }
]
return (
<View>
<FlatList
data={data}
renderItem={({ item }) =>
<Text>{item.key}</Text>}
/>
</View>
)
}
Requires 2 props:
data
renderItem
[ ]
({item}) => { }
render() {
const data = [
{ name: "Chris" },
{ name: "Amanda" }
]
renderItem = ({ item }) => {
return <Text>{item.name}</Text>
}
return (
<View>
<FlatList
data={data}
renderItem={this.renderItem}
keyExtractor={item => item.name}
/>
</View>
)
}
keyExtractor
render() {
const data = [
{ name: "Chris" },
{ name: "Amanda" }
]
renderItem = ({ item }) => {
return <Text>{item.name}</Text>
}
return (
<View>
<FlatList
data={data}
renderItem={this.renderItem}
keyExtractor={item => item.name}
ItemSeparatorComponent={() => <View />}
/>
</View>
)
}
ItemSeparatorComponent
render() {
const data = [
{ name: "Chris" },
{ name: "Amanda" }
]
renderItem = ({ item }) => {
return <Text>{item.name}</Text>
}
return (
<View>
<FlatList
data={data}
renderItem={this.renderItem}
keyExtractor={item => item.name}
refreshing={this.state.refreshing}
onRefresh={this.onRefresh}
/>
</View>
)
}
onRefresh
code
code
code
constructor(props)
static getDerivedStateFromProps(nextProps, prevState)
render()
componentDidMount()
React Lifecycle methods - mounting
static getDerivedStateFromProps(nextProps, prevState)
render()
getSnapshotBeforeUpdate(prevProps, prevState)
componentDidUpdate(prevProps, prevState, snapshot)
React Lifecycle methods - mounting
react-navigation
The community solution to navigation is a standalone library that allows developers to set up the screens of an app with just a few lines of code.
Main types of navigators:
StackNavigator
SwitchNavigator
TabNavigator
DrawerNavigator
StackNavigator
npm i react-navigation --save
Step 1: Install react-navigation
yarn add react-navigation
or
createStackNavigator
Step 2: import createStackNavigator
import { createStackNavigator } from "react-navigation"
Step 3: Create navigation screens using components
const MyHomeRoutes = createStackNavigator({
Home: { screen: Home },
Info: { screen: Info }
},{
initialRouteName: "Info"
}
})
createStackNavigator takes 2 arguments:
Step 4: Render Navigation
AppRegistry.registerComponent("App", () => App)
StackNavigator - Basic Implementation
const Home = () => (
<Text>Hello from Home</Text>
)
const Info = () => (
<Text>Hello from Info</Text>
)
const App = StackNavigator({
Home: { screen: Home },
Info: { screen: Info }
})
AppRegistry.registerComponent("App", () => App)
code
npm i unstated --save
yarn add unstated
or
Unstated gives us 3 things:
Create container to store state by extending the Container class:
import { Container } from "unstated"
class RootStore extends Container {
// ...
}
export default RootStore
Container
Manage state in the Container using:
import { Container } from "unstated"
class RootStore extends Container {
state = { items: [] }
addItem = item => {
const newItem = { name: item.name, checked: false }
this.setState({ items: [...this.state.items, newItems] })
}
checkItem = selectedItem => {
this.setState({
items: this.state.items.filter(item => {
return item.name === selectedItem.name
? {name: item.name, checked: true }
: item
})
})
}
}
export default RootStore
state
setState
Container
import { PackingListScreen } from "../screens/packing-list-screen"
import { InputScreen } from "../screens/input-screen"
import { createStackNavigator } from "react-navigation"
import { Provider } from "unstated"
const RootStack = createStackNavigator(
{
Home: PackingListScreen,
Input: InputScreen
}
)
class App extends Component {
render() {
return (
<Provider>
<RootStack />
</Provider>
)
}
}
export default App
Stores Container instances
Provider's children subscribe to the instances
Provider
import React from "react"
import { Subscribe } from "unstated"
import { RootStore } from "./RootStore"
class MyScreen extends React.Component {
render() {
return (
<View>
<Subscribe to={[RootStore]}>
{rootStore => (
rootStore.items.map(item => <Text>{item.name}</Text>)
)}
</Subscribe>
</View>
)
}
}
Function as children
Subscribe
Takes:
&
code
Main methods:
setItem
multiGet
getItem
multiSet
setItem(key: string, value: string, ?(error) => void)
setItem
getItem(key: string, ?(error, result: ?string) => void)
getItem
setItem("username", "FrankTheTank")
getItem("username", (error, result) => console.log(error, result))
multiSet(keyValuePairs: Array<Array<string>>, ?(errors) => void)
multiSet
multiSet(
[
["username", "FrankTheTank"],
["password", "password_snake_cased"]
],
(errors) => console.log(errors)
)
multiGet(keys: Array<string>, ?(errors, result: Array<Array<string>>) => void)
multiGet
multiGet(
["username", "password"],
(errors, result) => console.log(result)
)
// [
// ["username", "FrankTheTank"],
// ["password", "password_snake_cased"]
// ]
code
react-native link
A component can specify the layout of its children using the flexbox algorithm. Flexbox is designed to provide a consistent layout on different screen sizes.
You will normally use a combination of:
flexDirection
alignItems
justifyContent
to achieve the right layout.
flex: number
container: {
flex: 1
},
box1: {
flex: 1,
backgroundColor: 'red'
},
<View style={styles.container}>
<View style={styles.box1} />
</View>
flex: number
container: {
flex: 1
},
box1: {
flex: 1,
backgroundColor: 'red'
},
box2: {
flex: 1,
backgroundColor: 'orange'
},
<View style={styles.container}>
<View style={styles.box1} />
<View style={styles.box2} />
</View>
flex: number
container: {
flex: 1
},
box1: {
flex: 1,
backgroundColor: 'red'
},
box2: {
flex: 2, // "Change flex from 1 to 2"
backgroundColor: 'orange'
},
<View style={styles.container}>
<View style={styles.box1} />
<View style={styles.box2} />
</View>
flexDirection
container: {
flex: 1
}
<View style={styles.container}>
<Text>Hello World</Text>
<Text>Hello World</Text>
<Text>Hello World</Text>
<Text>Hello World</Text>
</View>
- column
flexDirection
container: {
flex: 1,
flexDirection: 'row'
}
<View style={styles.container}>
<Text>Hello World</Text>
<Text>Hello World</Text>
<Text>Hello World</Text>
<Text>Hello World</Text>
</View>
- row
justifyContent
Determines the distribution of children along the primary axis.
flexDirection: column
flexDirection: row
⬆
⬇
⬅ ➡
justifyContent:
justifyContent:
<View style={styles.container}>
<Text>Hello World</Text>
<Text>Hello World</Text>
<Text>Hello World</Text>
<Text>Hello World</Text>
</View>
'center'
container: {
flex: 1,
justifyContent: 'center'
}
container: {
flex: 1,
justifyContent: 'flex-end'
}
container: {
flex: 1
}
'flex-end'
container: {
flex: 1,
justifyContent: "space-around"
}
'space-around'
container: {
flex: 1,
justifyContent: "space-between"
}
'space-between'
alignItems
Determines the distribution of children along the secondary axis.
flexDirection: column
⬆
⟷
⬇
⬅ ↕ ➡
alignItems: center
flexDirection: row
alignItems: center
Default - 'stretch'
horizontal axis
vertical axis
alignItems:
container: {
flex: 1,
alignItems: 'center'
}
'center'
in action
'flex-end'
<View style={styles.container}>
<Text>Hello World</Text>
<Text>Hello World</Text>
<Text>Hello World</Text>
<Text>Hello World</Text>
</View>
container: {
flex: 1,
alignItems: 'flex-end'
}
code
react-native link
StyleSheet
import { StyleSheet, View, Text } from ‘react-native'
const styles = StyleSheet.create({
text: {
color: 'red'
},
bigText: {
fontSize: 30
}
})
<Text style={[styles.text, styles.bigText]}>Hello World</Text>
Array of styles
StyleSheet
import { StyleSheet, View, Text } from ‘react-native'
const styles = StyleSheet.create({
text: {
color: 'red'
}
})
<Text style={[styles.text, { fontSize: 32 } ]}>Hello World</Text>
Combining inline styles with StyleSheet
Dynamic styling
state = {
warning: true,
}
render() {
const fontColor = this.state.warning ? 'red' : 'black'
return (
<View>
<Text style={{color: fontColor}}>Hello World</Text>
</View>
)
}
backgroundColor
background-color
vs
Main
non-flex styles
<View/>