Component Lifecycle
Each component has several “lifecycle methods” that you can override to run code at particular times in the process.
Methods prefixed with will are called right before something happens
Methods prefixed with did are called right after something happens.
Everytime we change the state of component, it will rerender itself
MOUNTING
These methods are called when an instance of a component is being created and inserted into the DOM:
-
Set default state using a constructor.
this.state = { loading: false, error: null, stockProduct, };
-
componentWillMount()
Do nothing here
render()
MOUNTED
-
This is the point when you should initiate AJAX requests
RECEIVING PROPS
-
Do nothing here
Updating
An update can be caused by changes to props or state. These methods are called when a component is being re-rendered:
-
Component rerender. Put the layout animation here
Do nothing here
Unmounting
This method is called when a component is being removed from the DOM:
-
Unregister listener
UPDATED
- componentDidUpdate
Setup
Mac dev env setup
-
Update Xcode
-
Homebrew https://brew.sh/
-
Node
brew install node
-
brew install watchman
-
npm install -g react-native-cli
if not permitted to install globally
sudo chown -R $USER /usr/local
(Enable the root user)[https://support.apple.com/en-us/HT204012]
-
mpn i
Start the RN server
npm start –reset-cache
Tools
(Crashlytics)[https://streetsmartdev.com/react-native-analytics-fabric/]
Project init
- react-native init AwesomeProject // Suggest: use upper case for the project name
- cd AwesomeProject
- npm start
- react-native run-ios
- npm i
babel
- Add dependency In package.json
"babel-eslint": "4.1.6",
"eslint": "1.10.3",
"eslint-config-airbnb": "2.1.1",
"eslint-plugin-react": "3.12.0",
"react-native-swipeout": "2.0.12",
"redux": "^3.3.1"
- Add .eslintrc
React and RN
React
- How a component behave
- Take a bunch of components work together
RN
- How to take the output from a component and place it on the screen
- Provide default core components (image, text)
Project structure
Component
View
Create a component
Functional component
- Used for static data, for presentational use
- Easy to write
const SomeComponent = () => {
return (
<Text>Some text</Text>
);
}
//Make component available to other part of the app
export default SomeComponent;
Note: this is a JSX. JSX is JS, also the XML will be converted to JS. Example can be found here.
Class Component
- Can add some functions
- Based on ES6 class
import React, {Component} from 'react'
class SomeComponent extends Component {
render(){
return (
<Text>Some text</Text>
);
}
}
and the following code have the same result
import React, {Component} from 'react'
class SomeComponent extends Component {
render = ()=>{
return (
<Text>Some text</Text>
);
}
}
Use Component
import SomeComponent from './src/component/SomeComponent'
<SomeComponent></SomeComponent>
Return a Component
We can only return one component!
// This is not allowed
const App = () =>{
return (
<Header headerText={'Albums'}/>
<AlbumList/>
)
}
//It's like you try to return two elements
const App = () =>{
return ( <Header headerText={'Albums'}/> )
return ( <AlbumList/> )
}
//And it will not work
Render
Render a component to screen means take the view and place it on mobile device.
ReactNative.AppRegistry.registerComponent('albums', () => SomeComponent)
//Only the 'root' compoennt uses 'AppRegistry'
//'albums' is the name of the application.
//' () => SomeComponent' is the function that returns the first component to run for our application
Import
The import statement is used to import bindings which are exported by another module.
ES6 feature, outside code out of file should be imported.
Use {} or not.
// if the binding is exported using 'export default myDefaultExport;' you should not use {} to import the binding
import myDefaultExport from '/modules/my-module.js';
// otherwith use
import {myExport} from '/modules/my-module.js';
Storage
Props, state and store
Props
Short for porperties
Passing data from parent component to child component
- Consider props immutable
- Use props for event handlers to communicate with child components. (parent, child communication)
//Parent provide the prop that the child is expecting
<ChildComponent contentPassToChild={'I am a child'}/>
//Child
const ChildComponent = (props)=>{
return(
<Text>{props.contentPassToChild}</Text>
)
}
Note that contentPassToChild
can be text, function ecc.
props.children
Father can pass any views to the child, and the child receive with props.children
//Father
const AlbumDetail =(props)=>{
return(
<Card>
<Text>{props.album.title}</Text>
</Card>
)
}
//Child
const Card =(props)=>{
return(
<View>
{props.children}
</View>
)
}
Destructure the props
const AlbumDetail = (props) => {
const {thumbnailStyle,headerContentStyle}=styles;
return (
<Card>
<CardSection>
<View>
<Image
style={thumbnailStyle}
source=
/>
</View>
<View style={headerContentStyle}>
<Text>{props.album.title}</Text>
<Text>{props.album.artist}</Text>
</View>
</CardSection>
</Card>
)
}
the code above can be writen in this way
attention to the ({album}) instead of (album)
const AlbumDetail = ({album}) => {
const {title,artist,thumbnail_image} = album;
const {thumbnailStyle,headerContentStyle}=styles;
return (
<Card>
<CardSection>
<View>
<Image
style={thumbnailStyle}
source=
/>
</View>
<View style={headerContentStyle}>
<Text>{title}</Text>
<Text>{artist}</Text>
</View>
</CardSection>
</Card>
)
}
State
The state belongs to the component.
-
It is used for component internal record keeping, so we use it to update data.
- Use state for storing simple view state like wether or not drop-down options are visible.
- Never modify this.state directly, use this.setstate instead.
- State is the component that changed in this.
Functions
Object.assign()
Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. It will return the target object.
Object.assign({},todo,{
completed: !todo.completed; //toggle the todo, change state
}
)
//3 arg of todo:
{}: target
todo: source
{completed...}: overwrited data of source
Array
…
return [...list,0] //return a cancat 0 to the original list
splice
remove elements from array
list.splice(index,1)
slice
list.slice(0,index) //get sublist from 0 to index elements
concat
list.concat(element)
State management (Data management)
Redux
Exp2
MobX
https://github.com/mobxjs/mobx
Baobab
github https://github.com/Yomguithereal/baobab
http://www.christianalfoni.com/articles/2015_02_06_Plant-a-Baobab-tree-in-your-flux-application
http://www.christianalfoni.com/articles/2015_04_26_Handling-complex-state-with-Baobab
http://www.jianshu.com/p/6d4cce9d914f
File organization
We can create a index.js
file in folder src/components/common
that contains all the exports in this folder.
it can be imported from other files because it will be recognized automatically .
//index.js
import Alerts from './Alerts';
import Button from './Button';
import Card from './Card';
export {
Alerts,
Button,
Card
};
//Use it in other file
import {Alerts} from './components/common';
//instead of
import {Alerts} from './components/common/Alerts';
Logo
In Android:
the app icon is picked up from
In IOS:
- you should set
AppIcon
inImages.xcassets
. - you should upload 9 different size icons
29pt
29pt*2
29pt*3
40pt*2
40pt*3
57pt``57pt*2
60pt*2
60pt*3
.”
APIs
Linking
Open webpage Linking.openURL(url)
Debug
Android debug
Simulator debug menu on the Android Simulator click Cmd + M
Launch emulator
-
emulator -list-avds
emulator located in folder:
${ANDROID\_SDK}/tools/emulator
which on Mac located at~/Library/Android/sdk/tools/emulator
Cmd is
~/Library/Android/sdk/tools/emulator -list-avds
-
emulator @Nexus\_4\_Android\_4\_4\_API\_19
Debug on device
-
Check if your device is connected.
Run
adb devices
from theandroid_sdk/platform-tools/
directory. If connected, you’ll see the device name listed as a “device.” i.e.ce041604d44c0e1603 device
On mac command is
/Users/shi/Library/Android/sdk/platform-tools/adb devices
-
react-native run-android
-
Make sure your laptop and your phone are on the same Wi-Fi network.
-
find the computer IP address in System Preferences → Network.
-
Open the in-app Developer menu.
-
Go to Dev Settings → Debug server host for device.
-
Type in your machine’s IP address and the port of the local dev server (e.g. 192.168.1.11:8081).
iOS debug
Simulator debug menu on the iOS Simulator: Cmd + D
Show log: Cmd + D
-> Remote JS Debugging
Navigate to HomeScreen: Cmd + Shift + h
https://facebook.github.io/react-native/docs/running-on-device.html
Show simulator system log (when app crash): Cmd+/
Bugs
NPM modules get required from /Users/node_modules/ instead of the project directory
- rm -fr node_modules && npm i
- node_modules/react-native/packager/packager.sh –reset-cache
- watchman watch-del-all
Select “Debug JS Remotely” from the Developer Menu
Redux logger: https://github.com/evgenyrodionov/redux-logger#usage
Url: http://localhost:8081/debugger-ui
Pause on caught Exception
In chrome developer tool, sources-right most trangle button- active pause button
Inspect
- Nuclide: cmd-shift-p -> inspector show
- Emulator: Show inspector
Comment
{/Comment/}
Crash Reporting
Bug report system www.bugsnag.com
Build And Realease
Android
Debug Build
Bundle debug build:
react-native bundle --dev false --platform android --entry-file index.android.js --bundle-output ./android/app/build/intermediates/assets/debug/index.android.bundle --assets-dest ./android/app/build/intermediates/res/merged/debug
Create debug build:
cd android
./gradlew assembleDebug
Generated apk
will be located at
android/app/build/outputs/apk
open app/build/outputs/apk && cd ..
react-native bundle --dev false --platform android --entry-file index.android.js --bundle-output ./android/app/build/intermediates/assets/debug/index.android.bundle --assets-dest ./android/app/build/intermediates/res/merged/debug && cd android && ./gradlew assembleDebug && open app/build/outputs/apk && cd ..
iOS
react-native bundle --dev false --platform ios --entry-file index.ios.js --bundle-output ios/main.bundle
Rename the project
-
Rename the app name in app.json file
{ "name": "Album", "displayName": "Album" }
-
Rename the app name in index.android.js and index.ios.js
-
Rename the app name in package.json
-
Delete android and ios folder
-
Run
react-native link
-
Run ` react-native eject`
-
Run
react-native run-ios
-
Android SDK location
sudo nano ~/.bashrc
Add
export ANDROID_HOME=/Users/ufirstuser/Library/Android/sdk
-
Android Studio download ‘android-23’ and ‘Build Tools revision 23.0.1/25.0.2/26.0.1’
AppState
AppState
can tell you if the app is in the foreground or background, and notify you when the state changes.
NetInfo
NetInfo exposes info about online/offline status
Http (not Https) on iOS simulator
Modify plist which located in ios/Uper/info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>uupper.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
Note
Step to copy a project
- Add local.properties file in android folder with the sdk location
sdk.dir=/Users/shi/Library/Android/sdk
- Change iOS plist to allow http
- Install npm
- Run
react-native link
- Run
react-native run-ios
Attention!
- All the network request must be https
Airbnb React/JSX Style Guide
Eslint rules
https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules
Webstorm env setup
- install ESLint:
npm install -g eslint
Collapse by default
Settings/Preferences dialog -> Editor | General | Code Folding |
Online build service
bitrise https://www.bitrise.io/
E-book
React Native Skeleton
Snowflake React-Native Android iOS Starter App/ BoilerPlate
UI Library
Libraries
Barcode/QR code scanner
react-native-camera
npm install --save react-native-camera
react-native link react-native-camera
http://manojsinghnegi.com/blog/2017/08/18/Implementing-Barcode-scanner-in-react-native/
Trouble Shooting
- ENOENT: no such file or directory, uv_chdir
react-native upgrade
SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID_HOME environment variable.
Add local.properties file in android folder with the sdk location sdk.dir=/Users/shi/Library/Android/sdk
No bundle URL present, make sure you are running a package server
Solution 1
Kill app on iOS device and relaunch it
Solution 2
rm -r ./ios/build/
react-native run-ios
Warning: Each child in an array or iterator should have a unique “key” prop.
This is for render efficiency ; just add a unique key for each elements in the iterator like this
renderAlbums(){
return this.state.albums.map(album=>
<Text key={album.id}>{album.title}</Text>
)
}
Directory /src/components/AlbumDetail doesn’t exist
//The following is not work, because the directory name should contain ./
import AlbumDetail from '/src/components/AlbumDetail';
//like this
import AlbumDetail from '/src/components/AlbumDetail';
//but if you are not in the root folder, use
import AlbumDetail from './AlbumDetail';
Tutorial
Github repo for the The Complete React Native and Redux Course
React-Native学习指南 https://github.com/reactnativecn/react-native-guide
React Native 高质量学习资料汇总 http://www.jianshu.com/p/454f2e6f28e9
掘金list http://gold.xitu.io/tag/React%20Native
构建 F8 2016 App: http://f8-app.liaohuqiu.net/tutorials/building-the-f8-app/data/
Projects
Project list http://www.lcode.org/category/react-native-zong/react-native-source-code/
嘎嘎商城客户端 http://www.lcode.org/react-native-source-gagamall/