【水滴石穿】react-native-template-app

这个也是一个基础项目
地址如下https://github.com/ndlonghi/react-native-template-app

点击登陆跳转到首页

分析代码如
react-native-template-app/src/components/loading/index.js
loading效果

import React from 'react';
import {
  ActivityIndicator,
  Image,
  StyleSheet,
  View
} from 'react-native';

function Loading(props) {

  return (
    <View
      style={styles.container}
    >
      <Image
        source={require('../../assets/imgs/logo.png')}
        style={styles.logo}
      />
      <ActivityIndicator/>
    </View>
  )

}

const styles = StyleSheet.create({
  container: {},
  logo: {}
});

export default Loading;
//app.js
import React, {Component} from 'react';
import {Provider} from 'react-redux';
import {PersistGate} from 'redux-persist/integration/react';
//redux
//loading
//跳转路由
import {store, persistor} from "./src/store";
import Loading from "./src/components/loading/index";
import RootNavigator from "./src/navigation/containers";

export default class App extends Component {
  render() {
    return (
      <Provider
        store={store}
      >
        <PersistGate
          loading={<Loading/>}
          persistor={persistor}
        >
          <RootNavigator/>
        </PersistGate>
      </Provider>
    );
  }
}

src/store.js

import {
  applyMiddleware,
  createStore
} from 'redux';
import {persistStore, persistReducer} from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import {createReactNavigationReduxMiddleware} from 'react-navigation-redux-helpers';

import rootReducer from './reducers';

const persistConfig = {
  key: 'root',
  storage,
  blacklist: ['navigation']
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

const navigationMiddleware = createReactNavigationReduxMiddleware(
  'root',
  state => state.navigation
);

const store = createStore(
  persistedReducer,
  applyMiddleware(navigationMiddleware)
);

const persistor = persistStore(store);

export {store, persistor};

src/reducers/index.js

import {combineReducers} from 'redux';

import auth from "../services/auth/reducers";
import navigation from "../navigation/reducers";

export default combineReducers({
  auth,
  navigation
});

数据处理
src/services/api/index.js

import {Environments} from "../../environments/environments";
import type {Credentials} from "../../models/credentials";
import type {AuthObject} from "../../models/auth-object";
import type {ApiErrorResponse} from "../../models/api-error-response";

class Api {

  static getBackendConfig() {
    return Environments[Environments.env].backend;
  }

  handleError(error: any): ApiErrorResponse {
    let errorResponse: ApiErrorResponse = {
      error: error,
      text: 'An error ocurred. Please try again later.'
    };
    return errorResponse;
  }

  async get(url: string): any | ApiErrorResponse {
    return fetch(url, {
      method: 'GET'
    })
      .then((response) => {
        return response.json();
      })
      .catch((error: any) => {
        reject(this.handleError(error));
      })
  }

  async post(url: string, data: any): any | ApiErrorResponse {
    return fetch(url, {
      method: 'POST',
      body: JSON.stringify(data)
    })
      .then((response) => {
        return response.json();
      })
      .catch((error: any) => {
        reject(this.handleError(error));
      })
  }

  async login(credentials: Credentials): Promise<AuthObject | ApiErrorResponse> {
    //const query = await this.post(Api.getBackendConfig().url + Endpoints.LOGIN, credentials);
    //const {data} = await query.json();
    //return data;
    // Simulate api call
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({token: 'sanoteru'});
      }, 1000);
    })
  }

}

const Endpoints = {
  LOGIN: ''
};

export default new Api();
//src/services/auth/actions/action-tyes.js
export const SET_AUTH = 'SET_AUTH';
export const REMOVE_AUTH = 'REMOVE_AUTH';
///src/services/auth/actions/index.js
import {
  REMOVE_AUTH,
  SET_AUTH
} from "./action-tyes";
import type {AuthObject} from "../../../models/auth-object";

export const setAuth = (authObject: AuthObject) => ({
  type: SET_AUTH,
  payload: {
    authObject
  }
});

export const removeAuth = () => ({
  type: REMOVE_AUTH
});
//src/services/auth/reducers/index.js
import {
  REMOVE_AUTH,
  SET_AUTH
} from "../actions/action-tyes";

function auth(state = {}, action) {
  switch (action.type) {
    case SET_AUTH: {
      return {
        authObject: action.payload.authObject
      }
    }
    case REMOVE_AUTH: {
      return {
        authObject: null
      }
    }
    default: {
      return state;
    }
  }
}

export default auth;
//src/screens/loading.js
import React, {Component} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';

import {navigateToHome, navigateToLogin} from "../navigation/actions/index";
import LoadingLayout from '../components/loading/index';

const mapStateToProps = state => {
  return {
    auth: state.auth
  }
};

const mapDispatchToProps = dispatch => {
  return bindActionCreators({navigateToLogin, navigateToHome}, dispatch);
};

class Loading extends Component {

  componentDidMount() {
    this.redirect();
  }

  redirect = () => {
    if (this.props.auth.authObject) {
      this.props.navigateToHome();
    } else {
      this.props.navigateToLogin();
    }
  };

  render() {
    return <LoadingLayout/>
  }

}

export default connect(mapStateToProps, mapDispatchToProps)(Loading);
//src/screens/login.js
import React, {Component} from 'react';
import {
  Button,
  Image,
  SafeAreaView,
  StyleSheet,
  TextInput,
  View
} from 'react-native';
import {connect} from 'react-redux';
import {bindActionCreators} from "redux";

import {removeAuth, setAuth} from "../services/auth/actions/index";
import {navigateToHome} from "../navigation/actions/index";
import type {AuthObject} from "../models/auth-object";
import type {ApiErrorResponse} from "../models/api-error-response";
import Api from '../services/api/index';

const mapDispatchToProps = dispatch => {
  return bindActionCreators({setAuth, removeAuth, navigateToHome}, dispatch);
};

class Login extends Component {

  handleSubmit = () => {
    Api.login({
      email: 'mobile@4rsoluciones.com',
      password: 'aoeu'
    })
      .then((auth: AuthObject) => {
        this.props.setAuth(auth);
        this.props.navigateToHome();
      })
      .catch((error: ApiErrorResponse) => {
        this.props.removeAuth();
      })
  };

  render() {
    return (
      <SafeAreaView style={styles.container}>
        <View>
          <Image
            source={require('../assets/imgs/logo.png')}
            style={styles.logo}
          />
          <TextInput
            style={styles.input}
            placeholder="Username"
            placeholderTextColor="white"
          />
          <TextInput
            style={styles.input}
            placeholder="Password"
            placeholderTextColor="white"
            secureTextEntry={true}
          />
          <Button
            onPress={this.handleSubmit}
            title="Log in"
          />
        </View>
      </SafeAreaView>
    )
  }

}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'white',
  },
  logo: {
    width: 200,
    height: 80,
    resizeMode: 'contain',
    marginBottom: 10,
  },
  input: {
    marginBottom: 10,
    width: 250,
    height: 50,
    paddingHorizontal: 10,
    borderRadius: 5,
    backgroundColor: '#838383',
    color: 'white',
  }
});

export default connect(null, mapDispatchToProps)(Login);

login引用的是这里的api

import {Environments} from "../../environments/environments";
import type {Credentials} from "../../models/credentials";
import type {AuthObject} from "../../models/auth-object";
import type {ApiErrorResponse} from "../../models/api-error-response";

class Api {

  static getBackendConfig() {
    return Environments[Environments.env].backend;
  }

  handleError(error: any): ApiErrorResponse {
    let errorResponse: ApiErrorResponse = {
      error: error,
      text: 'An error ocurred. Please try again later.'
    };
    return errorResponse;
  }

  async get(url: string): any | ApiErrorResponse {
    return fetch(url, {
      method: 'GET'
    })
      .then((response) => {
        return response.json();
      })
      .catch((error: any) => {
        reject(this.handleError(error));
      })
  }

  async post(url: string, data: any): any | ApiErrorResponse {
    return fetch(url, {
      method: 'POST',
      body: JSON.stringify(data)
    })
      .then((response) => {
        return response.json();
      })
      .catch((error: any) => {
        reject(this.handleError(error));
      })
  }

  async login(credentials: Credentials): Promise<AuthObject | ApiErrorResponse> {
    //const query = await this.post(Api.getBackendConfig().url + Endpoints.LOGIN, credentials);
    //const {data} = await query.json();
    //return data;
    // Simulate api call
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({token: 'sanoteru'});
      }, 1000);
    })
  }

}

const Endpoints = {
  LOGIN: ''
};

export default new Api();
//src/screens/home.js
import React, {Component} from 'react';
import {
  Button,
  SafeAreaView,
  StyleSheet,
  Text,
  View
} from 'react-native';
import {connect} from 'react-redux';
import {bindActionCreators} from "redux";

import {removeAuth} from "../services/auth/actions/index";
import {navigateToLogin} from "../navigation/actions/index";

const mapDispatchToProps = dispatch => {
  return bindActionCreators({removeAuth, navigateToLogin}, dispatch);
};

class Home extends Component {

  handleLogout = () => {
    this.props.removeAuth();
    this.props.navigateToLogin();
  };

  render() {
    return (
      <SafeAreaView style={styles.container}>
        <View>
          <Text>This is the home</Text>
          <Button
            onPress={this.handleLogout}
            title="Log out"
          />
        </View>
      </SafeAreaView>
    )
  }

}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
  }
});

export default connect(null, mapDispatchToProps)(Home);

关于navigation部分还进行了很多处理,项目不容易啊~

posted @ 2019-05-16 15:22  jser_dimple  阅读(427)  评论(0编辑  收藏  举报
/*function gotourl() { var url = "https://www.cnblogs.com/smart-girl/"; var localurl = document.url; if( localurl.substring(0,url.length) != url ) { location.href=url; } } gotourl();*/