Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Here demonstrated some code sample for user login flow. Try to get core part explained, some details are omitted for easy understanding.
- Some of the main dependencies:
- ```
- "flux": "^2.1.1",
- "react": "^16.0.0",
- "react-native": "^0.50.4",
- "react-native-navigation": "^1.1.251",
- "react-native-fbsdk": "^0.6.3",
- "react-native-image-picker": "^0.26.7",
- "react-native-maps": "^0.17.0",
- ```
- **LoginScreen.js**
- ```js
- import React, { Component } from 'react';
- import {
- Alert,
- StyleSheet,
- View,
- ScrollView,
- Text,
- TextInput,
- } from 'react-native';
- // Encapsulate functions to trigger async actions related to user onboarding
- import * as UserActionCreators from '../actions/UserActionCreators';
- // see usage in render
- import CustomTextInput from '../comp/CustomTextInput';
- // ThemedButton is used across app to provide consistent style
- // Also it contains a flipped style to reflect which mode it is in
- import ThemedButton from '../comp/ThemedButton';
- // SessionStore is singleton obtained from SharedServices, it basically check
- // if there is store instance created, return it. We can see SessionStore below
- const SessionStore = SharedServices.sessionStore;
- class LoginScreen extends Component {
- constructor(props) {
- super(props);
- this.state = {
- username: '', password: ''
- }
- }
- componentDidMount() {
- // subscribe to SessionStore
- this._sessionListener = SessionStore.addListener(this._onStoreChange)
- }
- componentWillUnmount() {
- this._sessionListener && this._sessionListener.remove();
- }
- _onStoreChange() {
- // get notified in different phase of request
- if (SessionStore.pending === true) return;
- if (SessionStore.error) {
- Alert.alert('Error', SessionStore.error);
- return;
- }
- if (SessionStore.ready) {
- // this screen registered with navigation, will be passed with navigator
- this.props.navigator.pop();
- }
- }
- handleInputChange(k, v) {
- this.setState({[k]: v})
- }
- renderLoginBtn() {
- return (
- <ThemedButton onPress={this._doLogin>
- <Icon name='ios-mail' size={24} />
- <Text> Log in with Email </Text>
- </ThemedButton>
- )
- }
- _doLogin = () => {
- const {username, password} = this.state;
- // check input validation status, trigger action if all good
- return UserActionCreators.requestLoginWithEmail(username, password)
- }
- render() {
- return (
- <ScrollView >
- // CustomTextInput can be equipped with 'type' prop which is function
- // to define the valid rule, e.g UserNameType need to be non empty, and valid email format
- <CustomTextInput
- value={this.state.username}
- keyboardType='email-address'
- onChange={this.handleInputChange.bind(this, 'username')}
- type={UserNameType}
- />
- <CustomTextInput
- value={this.state.password}
- secureTextEntry={true}
- onChange={this.handleInputChange.bind(this, 'password')}
- type={PasswordType}
- />
- {this.renderLoginBtn()}
- <Spinner waiting={SessionStore.pending} />
- </ScrollView>
- )
- }
- }
- ```
- **UserActionCreators.js**
- ```js
- import SharedDispatcher from '../SharedDispatcher';
- import {ActionTypes} from '../constants';
- // Encapsulate sending api request to proper endpoint
- import UserAPI from './UserAPI';
- // Singleton Flux dispatcher to dispatch actions
- // We extend it to be able to dispatch promise (async actions), call the real
- // dispatch after promise resolved or rejected, similar idea to redux thunk middleware
- const dispatcher = SharedDispatcher();
- export function requestLoginWithEmail(username, password) {
- // this is how we use dispatchAsync
- return dispatcher.dispatchAsync(
- UserAPI.login(username, password), ActionTypes.USER_LOGIN_EMAIL
- )
- }
- // authData is obtained from Facebook login SDK
- export function requestSignInWithFB(authData) {
- return dispatcher.dispatchAsync(
- UserAPI.logInWithFB(authData), ActionTypes.USER_LOGIN_FACEBOOK
- )
- }
- ```
- **UserAPI.js**
- ```js
- export function login(username, password) {
- // Parse is client wrapper to deal with backend api,
- // do encoding request parameters and decoding response object etc
- return Parse.User.login(username, password)
- .then(user => {
- // do other stuff, like update installation table
- // resolved with logged in user object
- // this will be dispatched along with action payload
- return user;
- })
- }
- ```
- **SessionStore.js**
- ```js
- // inital state
- var _state = {
- type: undefined,
- requestStatus: undefined,
- error: null
- }
- class SessionStore extends Store {
- get pending() {
- return _state.requestStatus === 'pending';
- }
- get ready() {
- return _state.requestStatus === 'ready' ? true : false;
- }
- __onDispatch(action) {
- const {type, payload} = action;
- switch (type) {
- case ActionTypes.USER_LOGIN_EMAIL:
- // deal with action payload
- let newState = {type, requestStatus: payload.status};
- if (payload.status === 'ready') {
- Object.assign(newState, payload.response);
- }
- if (payload.error) {
- Object.assign(newState, payload.error);
- }
- // merge with previous state to produce next state shape
- _state = {..._state, ...newState};
- // notify subscribed component
- this.__emitChange();
- break
- case ActionTypes.USER_LOGIN_FACEBOOK:
- // similar to normal log in
- default:
- break;
- }
- }
- }
- ```
Add Comment
Please, Sign In to add comment