react-navigation 实践

goBack 时回传参数

// A.js
class A extends React.Component {
  _handlePressLocationSelect = () => {
    const { navigation } = this.props;
    navigation.navigate(
      'B',
      {
        onSelect: this._onSelect
      }
    );
  }

  _onSelect = ({}) => {
    this.setState({
    });
  }
}
// B.js
class B extends React.Component {
  _onPressBack = ({}) => {
    const { navigation } = this.props;
    navigation.goBack();
    navigation.state.params.onSelect({});
  }
}

react-navigation 与 mobx 集成

// NavStore.js

import { observable, computed, action } from 'mobx';
import { NavigationActions } from 'react-navigation';

import AppNavigator from '@/AppNavigator';

const initialState = AppNavigator.router.getStateForAction(
  NavigationActions.init()
);

class NavStore {
  constructor(rootStore) {
    this.rootStore = rootStore;
  }

  @observable.ref _nav = initialState;

  @action
  dispatch = (action) => {
    const state = this.nav;

    const nextState = AppNavigator.router.getStateForAction(action, state);

    this._nav = nextState;
  }

  @computed
  get nav() {
    return this._nav;
  }
}

export default NavStore;
// App.js

import React from 'react';
import { observer } from 'mobx-react';
import store from '@/store';

import AppNavigator from '@/AppNavigator';

import {
  addNavigationHelpers
} from 'react-navigation';

@observer
class App extends React.Component {
  render() {
    const navigation = addNavigationHelpers({
      dispatch: store.navStore.dispatch,
      state: store.navStore.nav,
    });

    return (
      <AppNavigator navigation={navigation} />
    );
  }
}

export default App;

使用 decorator 配置 navigationOptions

开发中,很多 screen 的 Header 样式是相似的,通过使用 decorator 可以使 navigationOptions 的配置更加简便。

import SS from '@/utils/style-sheet';

export function greenHeader(options) {
  return function (target) {
    let prevOpts = {};
    if ('navigationOptions' in target) {
      prevOpts = target.navigationOptions;
    }

    target.navigationOptions = (props) => {
      if (typeof prevOpts === 'function') {
        prevOpts = prevOpts(props);
      }

      const opts = typeof options === 'function' ? options(props) : options;

      return Object.assign({
        headerStyle: {
          backgroundColor: '#75CA2A',
          borderBottomWidth: 0,
        },
        headerTitleStyle: SS.pre({
          color: '#ffffff',
          fontSize: '36rpx'
        }),
        headerTintColor: '#fff'
      }, prevOpts, opts);
    }
    return target;
  }
}

export function noBackTitle(options) {
  return function (target) {
    let prevOpts = {};
    if ('navigationOptions' in target) {
      prevOpts = target.navigationOptions;
    }

    target.navigationOptions = (props) => {
      if (typeof prevOpts === 'function') {
        prevOpts = prevOpts(props);
      }

      const opts = typeof options === 'function' ? options(props) : options;

      return Object.assign({
        headerBackTitleStyle: { display: 'none', }
      }, prevOpts, opts);
    }
    return target;
  }
}

这里定义了两个 decorator:greenHeader 用来生成绿色的 Header,noBackTitle 用来隐藏掉 Header 中后退按钮的 title。

使用示例:

@greenHeader({
  tabBarVisible: true,
  tabBarLabel: '订单',
  title: '我的订单',
})
class TabOrder extends React.Component {}

@screen.greenHeader({ title: '贷款详情' })
@screen.noBackTitle()
class LoanDetail extends React.Component {}

Changelog

  • 2017/11/22 增加 使用 decorator 配置 navigationOptions