项目修改

190 阅读2分钟

1.项目文件启动顺序

(1.)/index.js

import { StatusBar, Platform, View } from 'react-native';
import { Provider } from 'react-redux';
import Config from 'react-native-config';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from '~/modules/redux-app-config';
import * as WeChat from 'react-native-wechat';
import AppContent from './AppContent';
import codePush from 'react-native-code-push';
import NetInfoManager from '~/modules/services/netInfo'; // 引入网络状态变化

class App extends Component {
  UNSAFE_componentWillMount() {
    codePush.disallowRestart(); // 设置热更不允许重启
  }

  componentDidMount() {
    console.log('============= Config ============= ', Config);
    WeChat.registerApp(Config.WECHAT_ID); // 注册微信AppID
    if (Platform.OS === 'android') {
      StatusBar.setTranslucent(true);
      StatusBar.setBackgroundColor('transparent');
      StatusBar.setBarStyle('dark-content');
    }
  }

  render() {
    return (
      <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}> // 设置redux缓存
          <AppContent /> // 加载自定义的
        </PersistGate>
      </Provider>
    );
  }
}
App = codePush({ installMode: codePush.InstallMode.ON_NEXT_RESTART })(App); // 设置热更新下一次重启生效

export default App;

(2)/AppContent.js

import React, { Component } from 'react';
import {
  View,
  StyleSheet,
  Platform,
  BackHandler,
  ToastAndroid,
  StatusBar,
  PermissionsAndroid,
} from 'react-native';
import Promise from 'bluebird';

import UI from '~/modules/UI';
import { store, dispatch } from '~/modules/redux-app-config';
import i18n from '~/i18n';
import { getRouteName, checkPermission } from '~/modules/services/utils';
import AppWithNavigationState from './AppRouter';
import AppLoading from './AppLoading';
import AppEnv from './AppEnvModal';
import ContentLoader from '~/components/ContentLoader';
import EventTracking from '~/modules/services/event-tracking';

class AppContent extends Component {
  UNSAFE_componentWillMount() {
    if (Platform.OS === 'android') {
      BackHandler.addEventListener('hardwareBackPress', this.onBackAndroid.bind(this));
    }
    this.permissionsTrack(); // 权限埋点
    // if (!store.getState().userInfo.user) {
    //   asyncAction('USER_LOGIN');
    // }
  }

  componentWillUnmount() {
    if (Platform.OS === 'android') {
      BackHandler.removeEventListener('hardwareBackPress', this.onBackAndroid.bind(this)); //安卓点击两次返回退出app
    }
  }

  async permissionsTrack() {
    await Promise.delay(10 * 1000);
    const storagePer = await checkPermission(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE);
    const readPhonePer = await checkPermission(PermissionsAndroid.PERMISSIONS.READ_PHONE_STATE);
    const { readStorage, readPhoneState } = store.getState().permissionsInfo;
    if (!readStorage && storagePer) {
      EventTracking.track('t0101', 'r0130');
      EventTracking.track('t0105', 'r0130');
      dispatch('SET_PERMISSIONS_INFO', { readStorage: true });
    }
    if (!readPhoneState && readPhonePer) {
      EventTracking.track('t0101', 'r0131');
      EventTracking.track('t0105', 'r0131');
      dispatch('SET_PERMISSIONS_INFO', { readPhoneState: true });
    }
  }

  onBackAndroid() {
    // return false;
    const routeName = getRouteName(store.getState().nav);
    if (routeName === 'grade') {
      return true;
    }
    if (routeName !== 'lesson' && routeName !== 'pageRegister') {
      store.dispatch({ type: 'Navigation/BACK' });
      return true;
    }
    if (this.lastBackPressed && this.lastBackPressed + 2000 >= Date.now()) {
      // 最近2秒内按过back键,可以退出应用。
      return false;
    }
    this.lastBackPressed = Date.now();
    ToastAndroid.show('再按一次退出程序', ToastAndroid.SHORT);
    return true;
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={{ flex: 1 }}>
          <AppWithNavigationState />
        </View>
        <AppLoading /> // 加载loading
        <AppEnv /> // 加载设置环境modal
        <ContentLoader />
      </View>
    );
  }
}

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

export default AppContent;

(3)/.env.local .env.development .env.production 各个开发环境设置

(4)/js/modules/services/request.js 网络请求

import { Alert } from 'react-native';
import { dispatch, store } from '~/modules/redux-app-config';
import { Toast } from 'teaset';
import Global from '~/modules/global';

function checkStatus(response) {
  console.log(' ============ response ============ ', response);
  if (response.code === 401) {
    dispatch('GET_USERINFO'); // 如果网络请求返回的的code为401, 那么获取用户信息,重定向到登陆页面
  }
  return response;
}

function checkNet() {
  return store.getState().netInfoStatus.status;
}

/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
export default function request(url, options) {
  const status = checkNet();
  if (!status) {
    return new Promise(res => {
      Toast.fail('请检查网络');
      res({ msg: 'fail' });
    });
  }
  if (!url.startsWith('http')) {
    url = Global.getApiUrl() + url; // 设置请求url
  }
  const defaultOptions = {};
  const newOptions = { ...defaultOptions, ...options };
// 设置header请求头, 这里主要是加了token的header
  newOptions.headers = {
    Connection: 'close',
    type: 'getUserData',
    'Content-Type': 'application/json; charset=utf-8',
    ...newOptions.headers,
  };

  console.log(' ============ request ============ ', { url, newOptions });
  return Promise.race([
    fetch(url, newOptions),
    new Promise((resolve, reject) => {
      setTimeout(() => {
        reject(new Error('Request Timeout')); // 设置超时10秒
      }, 10000);
    }),
  ])
    .then(response => response.json())
    .then(checkStatus) // 检查网络
    .catch(e => {
      if (e.toString() === 'Error: Request Timeout') {
        Toast.fail('请求超时'); // 提示网络请求超时
      }
    });
}