Basic React Native Concepts

ES6

New variable types

let
const
var

NEVER

Sometimes

Always

ES6

// 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

  • function scoped   
// let declaration
function letTest() {
  let x = 1
  if (true) {
    let x = 2  // different variable
    console.log(x)  // 2
  }
  console.log(x)  // 1
}
var
  • global (declared outside any function)
  • block-scoped - only available in the block in which they are declared
let

ES6

const key = "mykey"

key = "newkey"

// error "key" is read only

New variable types - 

const
  • read-only reference to a value
  • variable cannot be reassigned

ES6

const person = {
  name: "Jennifer",
  age: 43,
  occupation: "Dentist",
}

person.name = "Jim"

New variable types - 

const
{
  "age": 43,
  "name": "Jim",
  "occupation": "Dentist"
}

ES6

Arrow functions

ES5

ES6

var sayName = 

 

function() {}

 

const sayName = 

 

() => {}

 

() => {} 
this

bound to global

ES6

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

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

ES6

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

...

ES6

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"

Further Reading

https://github.com/lukehoban/es6features

ES6

JSX

  • JSX is a syntax extension, compiled in a preprocessor step that adds XML syntax to JavaScript.

 

  • You can definitely use React without JSX but JSX makes React a lot more elegant.

Candy Time!

JavaScript XML

  • For a candy, JSX stands for...

JSX

This:

Compiles to:

<Text color="blue" >
  Click Me
</Text>
React.createElement(
  Text,
  {color: "blue"},
  "Click Me"
)

React Native uses JSX

const MyComponent = <Text>Hello World</Text>
const MyImage = <Image source={someSource} style={styleObj} />
{ MyComponent }


{ MyImage }

Embedding Expressions into JSX

const person = { name: "Chris", age: 22 }
const MyComponent = <Text>Hello { person.name }</Text>

Embedding Expressions into JSX

const person = { name: "Chris", age: 22 }
const MyComponent = <Text>Hello { getName() }</Text>
const getName = () => person.name 

Logic with JSX

const person = { name: "Chris", age: 22 }

if (person.age >= 20) {
  return <Text>{person.name}</Text>
} else {
  return <Text>Age is below 20</Text>
}

Logic with JSX

const person = { name: "Chris", age: 22 }

<Text>{person.name} {person.age > 20 ? "Is over 20" : "Is not over 20" }</Text>

ternary operator

JSX Children

<View>
  <Text>Hello!</Text>
  <Text>Good to see you here.</Text>
</View>

JSX Variables

const greeting = (  
  <View>
    <Text>Hello!</Text>
    <Text>Good to see you here.</Text>
  </View>
)

// in component

{ greeting }

JSX

  • Concise HTML/XML-like structures in the same file as our JavaScript code

 

  • These expressions ➡ actual JavaScript code

tl;dr

  • Syntactic sugar

Hello Packing List

  • Start new project
  • Examine structure
  • Create first component
  • Pass props

Preview

React Native Core Components

  • View
  • ScrollView
  • Text
  • TextInput
  • Image
  • TouchableOpacity

React Native vs HTML

HTML React Native
<div> <View>
<p> <Text>
<input /> <TextInput />
<button> <TouchableOpacity />

Basic React Native Concepts

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.

Styling

Styles can be created one of three ways:

  • inline
  • object  
  • StyleSheet declaration

Styling

inline styles

<Text style={{color: "red"}}>Hello World</Text>

<View style={{width: 300}}>

Styling

style object

const styles = {
  text: {
    color: "red"
  }
}

<Text style={styles.text}>Hello World</Text>

Styling

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

Hello World

  • Get app running

 

  • Examine structure

 

  • Create functional component

 

  • Pass props

Re-cap

Step 1

  • Able to write to and read from local state

 

  • Introduce local state

Preview

Component State

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 />
  • Contains local state  
  • Lifecycle methods

Basic React Native Components

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

Basic React Native Concepts

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

  • Component needs to be re-rendered with the updated state
setState
  • Enqueues changes to the component state

TextInput

Common props

  • value
  • placeholder
  • onChangeText
(val) => val: string
"string"
  • onSubmitEditing
"string"
() => {}
code

Step 1

  • Able to write to and read from local state

 

  • Introduce local state

Re-cap

Step 2

Step 2

  • Introduce "items" array into local state

 

  • Move the input to its own function - add a wrapper &  buttons

Preview

  • Able to push inputted item into the items array
  • Able to clear items from the items array
code

Step 2

  • Introduce "items" array into local state

 

  • Move the input to its own function - add a wrapper &  buttons

Re-cap

  • Able to push inputted item into the items array
  • Able to clear items from the items array

Step 3

Step 3

  • Manipulate controlled component - clear input with ref

 

  • Introduction to controlling a component - TextInput

Preview

  • Add more styling - corners & shadows

Refs

Can be assigned one of two ways:

  • String
  • Callback
ref="myComponent"
ref={(ref) => this.myComponent = ref}
code

Step 3

  • Manipulate controlled component - clear input with ref

 

  • Introduction to controlling a component - TextInput

Re-cap

  • Add more styling - corners & shadows

Step 4

Step 4

  • Intro to FlatList

 

  • Add ability to "check" an item

Preview

FlatList

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}) => { }

FlatList

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
  • Key is used for caching
  • To track item re-ordering

FlatList

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

FlatList

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

Step 4

  • Intro to FlatList

 

  • Add ability to "check" an item

Re-cap

Step 5

Preview

  • Review larger project
  • Setup basic project folder structure
  • /src/app
  • /src/screens

Example Project

Chain React App 2018

code

Step 5

Re-cap

  • Review larger project
  • Setup basic project folder structure​
  • /src/app
  • /src/screens

Step 6

Preview

  • Get ready for multiple screens
  • Create “components” folder - /components
  • Create Button component
  • Create ListInput component
code

Step 6

Re-cap

  • Get ready for multiple screens
  • Create “components” folder - /components
  • Create Button component
  • Create ListInput component

Step 7

Step 7

  • Install React Navigation

Preview

  • Pass the items via navigation ➡ input-screen as props
  • Create an input-screen.js
  • Swap local state for navigation state on packing-list-screen
  • Integrate navigation state on input-screen
  • Refactoring exercise

Basic React Native Components

  • constructor(props)
  • static getDerivedStateFromProps(nextProps, prevState)
  • render()
  • componentDidMount()

React Lifecycle methods - mounting

Basic React Native Components

 
  • static getDerivedStateFromProps(nextProps, prevState)
  • render()
  • getSnapshotBeforeUpdate(prevProps, prevState)
  • componentDidUpdate(prevProps, prevState, snapshot)
    

React Lifecycle methods - mounting

Navigation

 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.

Navigation

Main types of navigators:

StackNavigator
SwitchNavigator
TabNavigator
DrawerNavigator

Navigation

StackNavigator
npm i react-navigation --save

Step 1: Install react-navigation

yarn add react-navigation

or

Navigation

createStackNavigator

Step 2: import createStackNavigator

import { createStackNavigator } from "react-navigation"

Navigation

Step 3: Create navigation screens using components

const MyHomeRoutes = createStackNavigator({
  Home: { screen: Home },
  Info: { screen: Info }
},{
  initialRouteName: "Info"
  }
})
  •  StackNavigatorConfig: object
  •  RouteConfigs: object

createStackNavigator takes 2 arguments:

Navigation

Step 4: Render Navigation

AppRegistry.registerComponent("App", () => App)

Navigation

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

Step 7

  • Install React Navigation

Re-cap

  • Pass the items via navigation ➡ input-screen as props
  • Create an input-screen.js
  • Swap local state for navigation state on packing-list-screen
  • Integrate navigation state on input-screen
  • Refactored

Step 8

Preview

  • Manage state with Unstated
  • https://github.com/jamiebuilds/unstated

Unstated

npm i unstated --save
yarn add unstated

or

Unstated

Unstated gives us 3 things: 

  • Container class
  • Subscribe component
  • Provider component

Unstated -

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

Unstated -

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

Unstated -

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

Unstated -

Subscribe

Takes:

  • to={[stores]}

&

code

Step 8

Re-cap

  • Manage state with Unstated
  • https://github.com/jamiebuilds/unstated

Step 9

Step 9

  • Persist items in AsyncStorage

Preview

  • Bring in AsyncStorage
  • Replace Stack Navigator ➡ Tabs Navigator

AsyncStorage

Main methods:

  • setItem
  • multiGet
  • getItem
  • multiSet

AsyncStorage

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))

AsyncStorage

multiSet(keyValuePairs: Array<Array<string>>, ?(errors) => void)
multiSet
multiSet(
  [
    ["username", "FrankTheTank"], 
    ["password", "password_snake_cased"]
  ],
  (errors) => console.log(errors)
)

AsyncStorage

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

Step 9

  • Persist items in AsyncStorage

Re-cap

  • Bring in AsyncStorage
  • Replace Stack Navigator ➡ Tabs Navigator

Step 10

  • Make app match prototype

Preview

  • Theme
  • Refined Styles - FlexBox
  • Styling exercise
  • Installing a native module - vector icons
  • react-native link

FlexBox

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.

FlexBox

flex: number
container: {
  flex: 1
},
box1: {
  flex: 1,
  backgroundColor: 'red'
},
<View style={styles.container}>
  <View style={styles.box1} />
</View>

FlexBox

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>

FlexBox

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>

FlexBox

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>
  • defines primary axis
  • default is column

 - column

FlexBox

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

FlexBox

justifyContent

Determines the distribution of children along the primary axis.

flexDirection: 
column
flexDirection:
row

 

 

⬅                   ➡

 

FlexBox

justifyContent:
  • flex-start
  • center
  • flex-end
  • space-around
  • space-between

FlexBox

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'

FlexBox

alignItems

Determines the distribution of children along the secondary axis.

flexDirection: column

 

 

 

 

⬅         ↕          ➡

 

 

alignItems: center
flexDirection: row
alignItems: center

Default - 'stretch'

horizontal axis

vertical axis

FlexBox

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

Step 10

  • Make app match prototype

Re-cap

  • Theme
  • Refined Styles - FlexBox
  • Styling exercise
  • Installing a native module - vector icons
  • react-native link

Styling + Flexbox

Styling

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

Styling

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

Styling

Dynamic styling

state = {
  warning: true,
}

render() {
  const fontColor = this.state.warning ? 'red' : 'black'
  return (
    <View>
      <Text style={{color: fontColor}}>Hello World</Text>
    </View>
  )
}

Styling

  • Styles usually match CSS
backgroundColor
background-color

vs

  • Prop names are camelCased

Styling

  • width / height - number

Main

non-flex styles

<View/>
  • top / left / bottom / right  - number
  • position - string (absolute, relative)
  • padding - number
  • margin - number
  • borderWidth - number
  • borderColor - color
  • backgroundColor - color

Basic React Native Concepts

By Infinite Red

Basic React Native Concepts

  • 1,807