- React Native Basics Tutorial - https://learn.handlebarlabs.com/p/react-native-basics-build-a-currency-converter
- Redux - http://redux.js.org/docs/basics/
- React Native Resources - https://github.com/jondot/awesome-react-native
- React Native Newsletter - http://reactnative.cc/
- Initial Setup
- React Native Basics
2.1. Basic Structure
2.2. Components
2.3. Props
2.4. State
2.5. One Way Binding - Vertical Scrolling List
- Navigation
- Forms
- Storage
- Network Calls
- On your smartphone, download the app iOS & Android
- On your PC, go to https://snack.expo.io/
- Go to https://expo.io/@junxiang92/tgifhack-todolist and scan the QR Code in Expo App
- Download https://expo.io/tools and Install.
- Download https://nodejs.org/en/download/ and Install.
- Download the project here.
- Open a
cmd/Terminal
onWindows/Mac
and navigate to the folder. - Run
npm install
. - Open
Expo XDE
and Open the Project. - Click
Share
and scan the QR Code using the Expo Client on your smartphone.,
https://reactjs.org/ React is built by Facebook and advertised as learn once write anywhere. Today, React can be used to build the following applications.
- Web Applications - https://github.com/facebook/react
- Mobile Applications - https://github.com/facebook/react-native
- Console Applications - https://github.com/Yomguithereal/react-blessed
- Desktop Applications - https://github.com/electron/electron
// Import Libraries
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Constants } from 'expo';
// Import Local Files
import AssetExample from './components/AssetExample';
// React Component
export default class App extends Component {
// Lifecycle
// constructor() -> render() -> componentDidMount()
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
this.setState({
...
});
}
// Generate UI
render() {
return (
<View style={styles.container}>
<Text>
Change code in the editor and watch it change on your phone!
Save to get a shareable url.
</Text>
</View>
);
}
}
// CSS Styles
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});
Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. In this workshop, we will be splitting Components into screens
and components
folder but both would mean the same thing.
- Open up https://snack.expo.io/HJ-9ypt0W and load it onto your mobile phone
- Change some of the text and see how it works
- Find where to change up the text inside of
<AssetExample />
- Try copying and pasting
<AssetExample />
, what happens? - Replace
<AssetExample />
with<TodoItem />
- Delete
<AssetExample />
https://facebook.github.io/react-native/docs/props.html Props are parameters for components. Think of it as initialising the parameters of a new class. These parameters are read-only. To update, we got to use a callback.
// TodoList.js
<TodoRow name={this.todo} onPress={this.onPress.bind(this)} />
// TodoRow.js
render() {
<Text>
{this.props.name}
<Button onPress={this.props.onPress} name="Save" />
</Text>
}
Edit TodoItem.js
to use props from app.js
- https://snack.expo.io/HyLRUdt0W
- In
app.js: 26
, Addtodos.map(todo => (<TodoItem item={todo}/>))
- In
TodoItem.js: 7
, Replacevar item = ...
withvar item = this.props.item
- Play around with it. Try adding a date field.
<TodoItem item={todo} date="3 Nov" />
https://facebook.github.io/react-native/docs/state.html Props are set by the parent and they are fixed throughout the lifetime of a component. For data that is going to change, we have to use state.
constructor() {
super();
this.state = {
todos: []
}
}
addTodo(todo) {
this.setState({
todos: this.state.todos.concat(todo),
})
}
Add a Button
that adds new Todos
- https://snack.expo.io/rkOa9utRW
- Copy the array with
let todos = this.state.todos.slice()
- Add a new todo with
todos.push(todo)
- Set the new state
this.setState({ todos })
- Try to create a button that delete todos
https://hashnode.com/post/why-does-react-emphasize-on-unidirectional-data-flow-and-flux-architecture-ciibz8ej600n2j3xtxgc0n1f0 React unlike Angular does not allow you to update a parent class data from a child class. This allows data to flow in a single direction and allow the management of the state to be handled in a single location.
Let's update a Todo when pressed.
- https://snack.expo.io/rkf9aKKCb
- Call a function when an
TodoItem
is pressed.
onItemPress(index) {
let todos = this.state.todos.slice();
// Update Todo
todos[index].txt = "Updated Todo";
this.setState({ todos });
}
- In
app.js: 50
, Pass the function as props to<TodoItem />
<TodoItem item={todo} index={i} onPress={this.onItemPress.bind(this)}/>
- Try to change the code to delete when pressed instead
todos.splice(index, 1);
https://facebook.github.io/react-native/docs/flatlist.html Component designed for efficient display of vertically scrolling lists of changing data. Examples include Contacts app, Whatsapp Group
- https://snack.expo.io/HkmWG9YC-
- In
app.js: 63
, update the code.
<FlatList
data={this.state.todos}
renderItem={({ item }) => (<TodoItem item={item} onPress={() => this.onPress(item)}/>)}
keyExtractor={(item, index) => index}
style={styles.listView}
/>
- How can you generate 50 items instead of 20? Completed Version
Screens are essentially components. They are different in a sense where they belong to themselves and not dependant on another component to use them.
This is how routes are defined. There are two main Navigators:
- StackNavigator - Provides a way for your app to transition between screens where each new screen is placed on top of a stack. Example: WhatsApp (We will only be using this).
- TabNavigator - Used to easily set up a screen with several tabs. Example: Instagram.
- DrawerNavigator - Side Panel where it provides functionality such as Profiles.
StackNavigator
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import HomeScreen from './screens/HomeScreen';
import EditScreen from './screens/EditScreen';
import {
StackNavigator
} from 'react-navigation';
// Define all your routes
export default StackNavigator({
Home: {screen: HomeScreen},
Edit: {screen: EditScreen},
})
In a Screen Component, this is the function to navigate to another screen.
this.props.navigation.navigate('Edit', { params });
MainScreen.js
class MainScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigate } = this.props.navigation;
return (
<Button
title="Go to Jane's profile"
onPress={() =>
navigate('Profile', { name: 'Jane' })
}
/>
);
}
}
This puts a title on the Status Bar.
class HomeScreen extends React.Component {
static navigationOptions = {
title: "Todo List"
};
When passing props between Screens
, instead of
this.props
it is
this.props.navigation.state.params
app.js
content has been moved into HomeScreen.js
. Let's click on an item and show that that is an item to be edited.
- https://snack.expo.io/rJPl8qFAW
- Update
HomeScreen.js: 36
to navigate toEditScreen.js
and passitem
as params. - In
EditScreen.js
, edit the code to display the item passed, if not, show it asNew Item
https://github.com/gcanti/tcomb-form-native Easy way to create forms for user to fill up content.
var Form = t.form.Form;
var Todo = t.struct({
todoId: t.maybe(t.Integer),
txt: t.Str,
complete: t.Bool
});
var options = {
fields: {
todoId: {
hidden: true
},
txt: {
label: 'To-Do Item',
placeholder: 'enter a to do item here',
autoFocus: true
}
}
};
<Form
ref="form"
type={Todo}
onChange={this._onChange}
options={options}
value={item}/>
var value = this.refs.form.getValue();
Try adding a new field, like a date field.
- https://snack.expo.io/BJg0y2cKAW
- In
EditScreen.js
, Look into https://github.com/gcanti/tcomb-form-native#dates and Add a Date field - In
TodoItem.js
, Display your dates
- There might be some bugs Completed Version
https://facebook.github.io/react-native/docs/asyncstorage.html Storing data into the phone database itself
try {
await AsyncStorage.setItem('@MySuperStore:key', 'I like to save it.');
} catch (error) {
// Error saving data
}
try {
const value = await AsyncStorage.getItem('@MySuperStore:key');
if (value !== null){
// We have data!!
console.log(value);
}
} catch (error) {
// Error retrieving data
}
https://snack.expo.io/HJDyCqKCW
Let's try storing your mode selected to Hide/Show Completed
into the database
https://facebook.github.io/react-native/docs/network.html Network calls allows you to access an API resource on the internet.
try {
const data = await fetch('https://2fc2398d.ngrok.io/todos');
this.initialise(await data.json());
} catch (err) {
console.log(err);
}
try {
const data = await fetch('https://2fc2398d.ngrok.io/todos', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(item)
});
return await data.json();
} catch (err) {
console.log(err);
}
https://snack.expo.io/BycasnYC-
Implement the createTodo
& updateTodo
functions