Basic React Native Concepts

ES6

New variable types

let
const
var

NEVER

Sometimes

Always

ES6

// var declaration
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
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"

// Uncaught TypeError:
// Assignment to constant variable.

New variable types - 

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

ES6

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

New variable types - 

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

person.name = "Jim"

{
  name: "Jennifer",
  age: 43,
  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: "Austin",
  sports: ["football", "tennis"]
}
// "Chris", "6'1", "Austin"

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.

JSX

For a candy...

JSX stands for:

JavaScriptXML

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

Summary

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

🍛 Lunch 🍛 

Panel

Step 1

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

Styles Intro

Styling

  • Styles usually match CSS
backgroundColor
background-color

vs

  • Prop names are camelCased

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

  • 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

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

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'
}
Play

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

break

Welcome Day 2

Review

StoryBook

Whack-A-Mole

Packing List

Preview

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

Packing List

Re-cap

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

Navigation

  • Install React Navigation

Preview

  • Pass the items via navigation ➡ input-screen as props
  • Create an input-screen.js

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)

Navigation

Each screen component in your app is provided with the navigation prop automatically.

  • navigate - go to a screen by key
  • getParam - is a helper to access a param that may be on the route
  • state - current navigation state/routes
  • goBack - go back to a screen by key or one screen

It looks like this:       this.props.navigation

Common methods on this.props.navigation

code

Drawer Navigator

createDrawerNavigator

import createDrawerNavigator

import { createDrawerNavigator } from "react-navigation"

Drawer Navigator

Create Drawer routes using screens

const DrawerStack = createDrawerNavigator(
  {
    Home: HomeScreen,
    Input: InputScreen 
  },
  {
    drawerWidth: 250
  }
)
  •  DrawerNavigatorConfig: object
  •  RouteConfigs: object

createDrawerNavigator can also take 2 arguments:

Drawer Navigator

moreCode

Navigation

  • Install React Navigation

Re-cap

  • Pass the items via navigation ➡ input-screen as props
  • Create an input-screen.js

State Management

When is setState not enough?

🍛 Lunch 🍛 

Panel

Add Unstated

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

Add Unstated

Re-cap

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

Async Storage

Step 9

  • Persist items in AsyncStorage

Preview

  • Bring in AsyncStorage

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

AsyncStorage

  • Persist items in AsyncStorage

Re-cap

  • Bring in AsyncStorage

Tests

break

Energy Up Exercise

Navigation Tabs

Tab Navigator

createBottomTabNavigator

import createBottomTabNavigator

import { createBottomTabNavigator } from "react-navigation"

Tab Navigator

Create Tab routes using screens or other navigators

const Tabs = createBottomTabNavigator(
  {
    Home: HomeScreen,
    Input: InputScreen 
  },
  {
    initialRouteName: "Home",
    tabBarOptions: {
      activeBackgroundColor: "orange",
      inactiveBackgroundColor: "yellow"
    }
  }
)
  •  BottomTabNavigatorConfig: object
  •  RouteConfigs: object

createBottomTabNavigator can also take 2 arguments:

Tab Navigator

Step 10

Step 10

  • Make app match prototype

Preview

  • Styling exercise
  • Installing a native module - vector icons
  • react-native link
  • Tabs Navigator
code

Step 10

  • Make app match prototype

Re-cap

  • Styling exercise
  • Installing a native module - vector icons
  • react-native link
  • Tabs Navigator

See You Tomorrow!

Welcome Day 3

TypeScript/Flow

fetch

fetch

fetch("https://www.tacobell.com", {method: "get"})
  .then((response) => response.json())
  .then((responseJson) => {
    return responseJson.tacos
  })
  .catch((error) => {
    console.error(error)
  })
  • API for networking

Raw example:

  • Returns a Promise
  • Comes for free with React Native
code

fetch

Networking Libraries

Networking Libraries

Axios Example

Networking Libraries

Networking Libraries

Apisauce Example

Andross

Bowser

🍛 Lunch 🍛 

Panel

Build Your Own App

Examples

  • Conference App

  • Textables App

  • Packing List App - deeper

  • Soundboard App

  • Tour App - Austin

  • Receipt Management App

Final Farewell

React Advanced London - React Native Concepts

By Infinite Red

React Advanced London - React Native Concepts

Slides for the uShip React Native Fundamentals Workshop, presented by Infinite Red Academy. All Rights Reserved.

  • 847