ReactJS
CALCULATOR: import classes from react-native
... import { View, Text, AppRegistry } from 'react-native';
Passing Arguments to Event Handlers
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button> <button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
React Native
Build native mobile apps using JavaScript and React React component: render: function() { return <div>Hi!</div>; } --> ReactJS --> BrowserDOM React component: render: function() { return <View>Hi!</View>; } --> React Native --> bridge --> iOS/Android An embedded instance of JavaScriptCore. React components with bindings to Native UI components. Manipulating calls into Objective C and java for behavior. And polyfills for some web APIs. Native App ( React Native Library ( JavaScript Engine ( React JS ( React Native JS Library, Your app ) ) ) )
Why use ReactJS?
Easy to understand what a component will render Easy to mix HTML and JS Uses full power of JS No complex two-way data flow React is fast! React dev tools Server-side rendering
Smallest React example
ReactDOM.render( <h1>Hello, world!</h1> document.getElementById('root') );
State
Represents internal state of the component Accessed via this.state When a component's state data changes, the rendered markup will be updated by re-invoking render() method render: function() { return <h3>Click count: <span className='label label-default'>{this.state.clicks}</span></h3>; }
React Native Modify and Run you App
The "npm start" starts a development server for you, and print a QR code in your terminal. Install the Expo Client app on your iOS or Android phone and connect to the same wireless network as your computer. Using the Expo Client app, scan the QR code from your terminal to open your project. Open App.js in your text editor of choice and edit some lines. The application should reload automatically once you save your changes.
CALCULATOR: History Screen
Use FlatList to display a list of results (like a UITableView in iOS) class HistoryScreen extends React.Component { render() { return ( <View style={{flex: 1}}> <FlatList data={historyData} renderItem={({item}) => <Text style={Style.historyItem}>{item.key}</Text> } /> </View> ); } }
Unmounting
componentWillUnmount
List Example
const numbers = [1, 2, 3, 4, 5]; const listItems = numbs.map((number) => <li>{number}</li> ); ReactDOM.render( <ul>{listItems}</ul>, document.getElementById('root') );
Who uses ReactJS?
facebook Instagram KhanAcademy asana Teradek Netflix Reddit Airbnb
Updation
props: componentWillReceiveProps-->shouldUpdateComponent-->(if true)-->componentWillUpdate-->render-->componentDidUpdate states: shouldComponentUpdate-->(if true)-->componentWillUpdate-->render-->componentDidUpdate
Composing Components
Components can refer to other components in their output. function Welcome(props) { return <h1>Hello, {props.name}</h1>; } function App() { return ( <div><Welcome name="Sara"/><Welcome name="Cahal"/></div> ); } ReactDOM.render(<App />, document.getElementById('root'));
Components
Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called "props") and return React elements describing what should appear on the screen. function Welcome(props) { return <h1>Hello, {props.name}</h1>; } class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } }
React vs React Native
React (aka ReactJS or React.js) is a JavaScript library you use for building dynamic, high performing, responsive UI for your web interface. React Native is an entire platform allowing you to build native, cross-platform mobile apps. React.js is the heart of React Native, and it embodies all React's principles and syntax, so the learning curve is easy.
CALCULATOR: Handling Touch Events
Update InputButton to use a Touchable view instead of View it currently uses. // InputButton.js ... render() { return ( <TouchableHighlight style={Style.inputButton} underlayColor="#193441" onPress={this.props.onPress}> <Text style={Style.inputButtonText}>{this.props.value}</Text> </TouchableHighlight> ) } we pass onPress prop to TouchableHighlight view so we'll need to provide that from our presenting Component //App.js ... _renderInputButtons() { ... inputRow.push(<InputButton value={input} onPress={this._onInputButtonPressed.bind(this, input)} key={r + "-" + i} /> ); } _onInputButtonPressed(input) { //handle press button events here } ...
Clock State Example
class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } render() { return ( <div> <h1>Hello, World!</h1> <h2>It is {this.state.date.toLocaleTimeString( )}.</h2> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') );
Map Example
const todoTimes = todos.map((todo) => <li key={todo.id}>{todo.text}</li> ); (key must be unique among siblings)
CALCULATOR: Add Input Buttons to Calculator Class
// App.js ... import InputButton from './InputButton'; const inputButtons = [[7, 8, 9], [4, 5, 6], [1, 2, 3], ['+', 0, '='], ["Show History"]]; class ReactCalculator extends Component { render() { return ( <View style={Style.rootContainer}> <View style={Style.displayContainer}></View> <View style={Style.inputContainer}>{this._renderInputButtons()}</View> </View> ) } } _renderInputButtons() { let views = [ ]; for (var r=0; r<inputButtons.length; r++) { let row = inputButtons[r]; let inputRow = [ ]; for (var i=0; i<row.length; i++) { let input = row[i]; inputRow.push(<InputButton value={input} key={r + "-" + i} /> ); } views.push(<View style={Style.inputRow} key={"row-" + r}>{inputRow}</View>); } return views; }
CALCULATOR: Pass data between screens
// Calculator screen _handleShowHistoryButtonPressed() { this.props.navigation.navigate('History', {history: equations}); } ... // History screen ... Render() { const {params} = this.props.navigation.state; const historyData = params ? params.history : [ ]; } ...
CALCULATOR: InputRow Styles
// Style.js ... inputRow: { flex: 1, flexDirection: 'row' } ...
CALCULATOR: InputButton Styles
// Style.js var Style = StyleSheet.create({ ... inputButton: { flex: 1, alignItems: 'center', justifyContent: 'center', borderWidth: 0.5, borderColor: '#91AA9D' }, inputButtonText: { fontSize: 22, fontWeight: 'bold', color: 'white' } });
Why was ReactJS developed?
Complexity of two-way data bind Bad UX from using "cascading updates" of DOM tree A lot of data on a page changing over time Complexity of Facebook's UI architecture Shift from MVC mentality
CALCULATOR: Adding Input Buttons
Creating an InputButton class that will be used for displaying each button on the calculator. // InputButton.js import React, { Component } from 'react'; import { View, Text } from 'react-native'; import Style from './Style'; export default class InputButton extends Component { render() { return ( <View style={Style.inputButton}> <Text style={Style.inputButtonText}>{this.props.value}</Text> </View> ) } }
What is ReactJS
Developed by Facebook Reach is a view layer library, not a framework like Backbone, Angular, etc. You can't use React to build a fully-functional web app. Reach challenges established best practices in traditional MV* frameworks
Component Lifecycle
Initialization Mounting Updation Unmounting
JSX
JSX (JavaScript XML) is a syntax extension to JavaScript. const element <h1 className="greeting">Hello, world!</h1>; You can embed any JavaScript expression in JSX by wrapping it in curly braces. function formatName(user) { return user.firstName + ' ' + user.lastName; } const element = { <h1> Hello, {formatName(user)}! </h1> }; JSX represents objects. Like XML, JSX tags have tag names, attributes, and children. Fundamentally, JSX just provided syntactic sugar for the React.createElement(component, props, ...children) function <MyButton color="blue" shadowSize={2}>Click me </MyButton> compiles into React.createElement(MyButton, {color: 'blue', shadowSize: 2}, 'Click me')
CALCULATOR: More things regarding state
Modify the inputValue in the button pressed events handler Add more states to save intermediate results and used as status indicators Saving calculation histories
React Native Stylesheets
React Native implements a strict subset of CSS. Here's an example of how stylesheets are created in React Native: var styles = StyleSheet.create({ container: { flex: 1, marginTop: 30}}); Then that style is applied using inline syntax: <View style={styles.container}>...</View>
CALCULATOR: React Navigation
React Navigation: Navigation between the Home Screen (Calculator) and the History Screen Install React Navigation in your project: npm install --save react-navigation Then you can quickly create an app with a home screen and a history screen import {StackNavigator} from 'react-navigation'; const App = StackNavigator({ Home: {screen: HomeScreen}, History: {screen: History}});
React Native Components
React native provides a number of built-in components Basic Components: View, Text, Image, TextInput, ScrollView iOS Components: DatePicker, ImagePicker, ActionSheet, ProgressView, TabBar Android Components: BackHandler, ProgressBar, TimePicker, Toast, Toolbar
CALCULATOR: Using State
State allows us to update the UI of our application based on dynamic data. The first thing we'll use State for is to update the display based on the numbers entered by the user // App.js ... class ReactCalculator extends Component { constructor(props) { super(props); this.state = { inputValue: 0 }; } render() { return ( <View style={Style.rootContainer}> <View style={Style.displayContainer}> <Text sytle={Style.displayText}>[this.state.inputValue}</Text> </View> <View style={Style.inputContainer}>{this._renderInputButtons()}</View> </View> ) } } Running the app, you should see that zero is displayed in Text view. That's because we set the value to this.state.inputValue, which we initialized to zero during the constructor.
State vs Props
State is referred to the local state of the components which cannot be accessed and modified outside of the component and can only be used and modified inside the component. Props make components reusable by giving components the ability to receive data from the parent component in the form of props. State: internal data vs Pros: External data State: can be changed vs Props: can't be changed State: private for component
React Native Installation
The easiest way is to use Github's Create React Native App. Make sure you have Node v6 or later. No Xcode or Android Studio installation required. Use 'npm': npm install -g create-react-native-app Then run the following commands to create and run a new React Native project: create-react-native-app MyApp cd MyApp npm start npm run iOS (for iOS emulator) npm run android (for android emulator)
Rendering a Component
When React sees an element representing a user-defined component, it passes JSX attributes to this component as a single object. We call this object "props". Renders "Hello, Sara" on the page: function Welcome(props) { return <h1>Hello, {props.name}</h1>; } const element = <Welcome name="Sara"/>; ReactDOM.render(element, document.getElementById('root'));
Name Form example
class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}><label>Name:<input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } }
Handling Events Toggle Example
class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(state => ({ isToggleOn: !state.isToggleOn })); } render() { return ( <button onClick={this.handleClick}>{this.state.isToggleOn ? 'ON' : 'OFF' } </button> ); } } ReactDOM.render(<Toggle />, document.getElementById('root') );
Mounting
componentWillMount --> render --> componentDidMount
Conditional Rendering Example
function UserGreeting(props) { return <h1>Welcome back!</h1>; } function GuestGreeting(props) { return <h1>Please sign up.</h1>; } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />; } ReactDOM.render( <Greeting isLoggedIn={false} />, document.getElementById('root') );
JSX Name Example
function formatName(user) { return user.firstName + ' ' + user.lastName; } const user = { firstName: 'Harper', lastName: 'Perez }; const element = ( <h1>Hello, {formatName(user)}!</h1> ); ReactDOM.render(element, document.getElementById('root'));
React Native Hello World
import React, { Component } from 'react'; import { Text, View, StyleSheet } from 'react-native'; import { Constants } from 'expo'; export default class App extends Component { render() { return ( <View style={styles.container}><Text style={styles.paragraph}>Hello, world!</Text></View> ); } } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', paddingTop: Constants.statusBarHeight, backgroundColor: '#ecf0f1' }, paragraph: { margin: 24, fontSize: 18, fontWeight: 'bold', textAlign: 'center', color: '#34495e' } });
CALCULATOR: Put styles into style.js
import Style from './Style'; ... <View style={Style.rootContainer}> <View style={Style.displayContainer}></View> <View style={Style.inputContainer}></View> </View>
CALCULATOR: Style.js content
import { StyleSheet } from 'react-native'; var Style = StyleSheet.create({ rootContainer: { flex: 1 }, displayContainer: { flex: 2, backgroundColor: '#193441' }, inputContainer: { flex: 8, backgroundColor: '#3E606F' } }); export default Style;
CALCULATOR: Laying out the Calculator
render() { return( <View style={{flex: 1}}> <View style={{flex: 2, backgroundColor: '#193441'}}></View> <View style={{flex: 8, backgroundColor:'#3e606f'}}></View> </View> ) }
Initialization
setup props and state