Биз жөнүндөБлогБайланыш
Мобилдик иштеп чыгуу2015-ж., 20-август 4 мин 10

React Native менен биринчи мобилдик тиркеме жасоо: Бишкек тажрыйбасы (2015)

AunimedaAunimeda
📋 Мазмуну

React Native менен биринчи мобилдик тиркеме жасоо: Бишкек тажрыйбасы (2015)

Кыскача: React Native 0.8–0.12 (2015-жылдагы версия) — JavaScript менен нативдик компоненттерди колдонуу мүмкүнчүлүгүн берди. Android поддержкасы сентябрь 2015-жылы кошулду. Өтө жаш фреймворк болгонуна карабай, production тиркеме үчүн жетиштүү болду.


2015-жылдагы React Native абалы

React Native Facebook тарабынан:

  • Март 2015 — iOS үчүн ачык булак катарында жарыяланды (v0.1)
  • Сентябрь 2015 — Android поддержкасы кошулду (v0.11)
  • Декабрь 2015 — v0.16, туруктуу болуп баштады

Биздин тиркемени июль–август 2015-жылы жаздык: iOS гана, Android жок болчу.


Орнотуу (iOS, 2015-жылдын жазы)

# Node.js 4.x, npm 2.x
npm install -g react-native-cli

react-native init DeliveryApp
cd DeliveryApp

# react-native v0.10 — iOS гана
react-native run-ios

Биринчи компонент: заказдар тизмеси

// OrdersList.js — React Native 0.10 стили

var React = require('react-native');

var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  ListView,
  TouchableHighlight,
  ActivityIndicatorIOS,
} = React;

// 2015: class компоненттери жаңы гана киргизилди
// Көпчүлүгү hala createClass колдонду
var OrdersList = React.createClass({

  getInitialState: function() {
    var ds = new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2
    });
    return {
      dataSource: ds.cloneWithRows([]),
      loading: true,
    };
  },

  componentDidMount: function() {
    this.fetchOrders();
  },

  fetchOrders: function() {
    fetch('https://api.delivery.kg/v1/orders', {
      headers: {
        'Authorization': 'Bearer ' + this.props.token,
        'Accept': 'application/json',
      }
    })
    .then(response => response.json())
    .then(data => {
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(data.orders),
        loading: false,
      });
    })
    .catch(error => {
      console.log('Error:', error);
      this.setState({ loading: false });
    });
  },

  renderRow: function(order) {
    return (
      <TouchableHighlight
        onPress={() => this.props.onSelectOrder(order)}
        underlayColor="#f0f0f0"
      >
        <View style={styles.row}>
          <Text style={styles.orderNum}>#{order.id}</Text>
          <Text style={styles.status}>{order.status_label}</Text>
          <Text style={styles.address}>{order.address}</Text>
        </View>
      </TouchableHighlight>
    );
  },

  render: function() {
    if (this.state.loading) {
      return (
        <View style={styles.center}>
          <ActivityIndicatorIOS size="large" />
        </View>
      );
    }

    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderRow}
      />
    );
  }
});

var styles = StyleSheet.create({
  row: {
    padding: 15,
    borderBottomWidth: 1,
    borderBottomColor: '#eee',
  },
  orderNum: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#333',
  },
  status: {
    fontSize: 14,
    color: '#666',
    marginTop: 4,
  },
  address: {
    fontSize: 13,
    color: '#999',
    marginTop: 2,
  },
  center: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

module.exports = OrdersList;

Навигация (Navigator — 2015 стандарты)

// App.js — navigator менен экрандар ортосунда которулуу
// React Navigation 2015-жылы жок болчу
// NavigatorIOS же Navigator колдонулду

var React = require('react-native');
var { Navigator, Text, View } = React;

var OrdersList = require('./OrdersList');
var OrderDetail = require('./OrderDetail');
var LoginScreen = require('./LoginScreen');

var App = React.createClass({
  render: function() {
    return (
      <Navigator
        initialRoute={{ name: 'Login', index: 0 }}
        renderScene={this.renderScene}
        navigationBar={
          <Navigator.NavigationBar
            routeMapper={{
              Title: (route) => <Text>{route.name}</Text>,
              LeftButton: (route, nav) => route.index > 0 ?
                <Text onPress={() => nav.pop()}>Артка</Text> : null,
              RightButton: () => null,
            }}
          />
        }
      />
    );
  },

  renderScene: function(route, navigator) {
    switch (route.name) {
      case 'Login':
        return <LoginScreen onLogin={(token) => {
          navigator.push({ name: 'Orders', index: 1, token });
        }} />;

      case 'Orders':
        return <OrdersList
          token={route.token}
          onSelectOrder={(order) => {
            navigator.push({ name: 'OrderDetail', index: 2, order, token: route.token });
          }}
        />;

      case 'OrderDetail':
        return <OrderDetail order={route.order} token={route.token} />;

      default:
        return <View><Text>Бет табылган жок</Text></View>;
    }
  }
});

AppRegistry.registerComponent('DeliveryApp', () => App);

API менен иштөө

// api.js — HTTP чалуулар

var API_URL = 'https://api.delivery.kg/v1';

var Api = {
  token: null,

  setToken: function(token) {
    this.token = token;
  },

  request: function(method, path, body) {
    var options = {
      method: method,
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
        'Authorization': 'Bearer ' + this.token,
      },
    };

    if (body) {
      options.body = JSON.stringify(body);
    }

    return fetch(API_URL + path, options)
      .then(response => {
        if (!response.ok) {
          throw new Error('HTTP ' + response.status);
        }
        return response.json();
      });
  },

  getOrders: function() {
    return this.request('GET', '/orders');
  },

  updateOrderStatus: function(orderId, status) {
    return this.request('PUT', '/orders/' + orderId, { status });
  },
};

module.exports = Api;

2015-жылдагы реалдуу кыйынчылыктар

1. JavaScript thread жана UI thread бөлүнгөн:

// setTimeout нативдик gesture менен конфликт берди
// Чечим: InteractionManager

var { InteractionManager } = require('react-native');

componentDidMount() {
  // Экран ачылып болгондон кийин гана маалымат жүктө
  InteractionManager.runAfterInteractions(() => {
    this.fetchOrders();
  });
}

2. Android 2015-жылы жок болчу:

Биздин клиент Android пайдалануучуларды да кааладı. Android поддержкасы сентябрь 2015-жылы гана чыкты. Ошол убакытка чейин Android версиясын WebView менен жасадык (PhoneGap).

3. Hot Reload жарымынан иштеди:

// 2015: Hot Reload кээде state'ти жоготту
// Чечим: componentDidMount'та маалымат кайра жүктөлсүн
componentDidMount() {
  if (__DEV__) {
    // Development режиминде ар дайым маалымат жүктө
    this.fetchOrders();
  }
}

Жыйынтыктар

Тиркемени 8 апта ичинде жасадык. iOS гана, 320 курьер колдонуучу. Нативдик Swift/ObjC тиркемеге салыштырмалуу:

React Native 2015 Нативдик iOS
Иштеп чыгуу убактысы 8 апта 12–15 апта
Баага $2,400 $4,500
Аткаруу Жакшы (жүктөлүүдө -20ms) Мыкты
Ката саны (биринчи ай) 4 краш 1 краш

React Native 2015 — толук эмес, бирок иштеген. Андан бери (2025-жылга чейин) фреймворк олуттуу жакшырды.

Ошондой эле окуңуз

Кыргызстандагы мобилдик тиркемелер 2013: Android жана iOS рыногунун биринчи талдоосуaunimeda
Мобилдик иштеп чыгуу

Кыргызстандагы мобилдик тиркемелер 2013: Android жана iOS рыногунун биринчи талдоосу

2013-жылы Кыргызстанда смартфон колдонуучуларынын саны биринчи жолу кнопкалуу телефон колдонуучуларынан ашты. Android рыногу — 68%, iOS — 12%, Nokia Symbian жана башкалар — 20%. Бишкекте биринчи жолу мобилдик тиркеме жасоонун мааниси пайда болду. Техникалык жана коммерциялык реалдуулук.

Vue.js менен биринчи долбоор: Бишкектеги тажрыйба (2016)aunimeda
Frontend

Vue.js менен биринчи долбоор: Бишкектеги тажрыйба (2016)

Vue.js 2.0 2016-жылдын октябрь айында чыкты. React'ка салыштырмалуу жеңилирек үйрөнүлгөн. Биз Бишкектеги бир кардар үчүн онлайн-дүкөндүн себет бөлүмүн Vue.js менен жасадык. Components, reactivity, Vuex — реалдуу мисалдар менен.

Express.js менен REST API сервер кантип жасоо: нөлдөн production'го чейин (2015)aunimeda
Backend

Express.js менен REST API сервер кантип жасоо: нөлдөн production'го чейин (2015)

Node.js 4 LTS + Express.js 4 — 2015-жылда PHP'га альтернатива катары пайда болду. Биз Бишкекте мобилдик тиркеме үчүн API сервер жасадык. Роутинг, middleware, валидация, JWT авторизация, MySQL — бардыгы бир жерде. Иштеген код мисалдары.

Бизнесиңизге IT иштеп чыгуу керекпи?

Веб-сайттарды, мобилдик тиркемелерди жана AI чечимдерин иштеп чыгабыз. Акысыз консультация.

Консультация алуу Бардык макалалар