簡體   English   中英

React Native + Redux:什么是最好的和首選的導航?

[英]React Native + Redux: What's the best and preferred navigation?

我想將Redux用於React Native。 目前我沒有設置數據管理,因此index.ios.js具有以下內容:

  renderScene(route, navigator){
    this._navigator = navigator

    return (
        <route.component navigator={navigator} {...route.passProps}/>
    )
  }

<Navigator
  configureScene={this.configureScene}
  initialRoute={{name: 'Login', component: Login}}
  renderScene={(route, navigator) => this.renderScene(route, navigator)}
  style={styles.container}
  navigationBar={
    <Navigator.NavigationBar
      style={styles.navBar}
      routeMapper={NavigationBarRouteMapper}
    />
  }
/>

我打算切換到Redux。 使用我當前的設置,不使用任何框架,只有例外是react-router,使用Redux導航的最佳方式是什么? 使用存儲,縮減器和操作的示例將非常有用。

編輯:現在應該使用react-navigation而不是NavigationExperimental。

-

我建議您使用NavigationExperimental而不是Navigator。 最后一個是折舊的。 RN文檔中有一個例子, 就在這里 它使用簡單的減速器來管理您的導航狀態。 但是你也可以使用Redux處理這個狀態,因為它是相同的邏輯。

這是我使用Redux和NavigationExperimental選項卡的設置:

navigator.js(注意:CardStack中的renderOverlay prop將在0.32中重命名為renderHeader)

import React from 'react';
import { NavigationExperimental } from 'react-native';
import { connect } from 'react-redux';
import { pop, push, selectTab } from './actions';

const {
  CardStack: NavigationCardStack,
} = NavigationExperimental;

class Navigator extends React.Component {
  constructor(props) {
    super(props);
    this._renderHeader = this._renderHeader.bind(this);
    this._renderScene = this._renderScene.bind(this);
  }

  _renderHeader(sceneProps) {
    return (
      <MyHeader
        {...sceneProps}
        navigate={this.props.navigate}
      />
    );
  }

  _renderScene(sceneProps) {
    return (
      <MyScene
        {...sceneProps}
        navigate={this.props.navigate}
      />
    );
  }

  render() {
    const { appNavigationState: { scenes, tabKey, tabs } } = this.props;

    return (
      <View style={{ flex: 1 }}>
        <NavigationCardStack
          key={`stack_${tabKey}`}
          navigationState={scenes}
          renderOverlay={this._renderHeader}
          renderScene={this._renderScene}
        />
        <Tabs
          navigationState={tabs}
          navigate={this.props.navigate}
        />
      </View>
    );
  }
}

const getCurrentNavigation = (navigation) => {
  const tabs = navigation.tabs;
  const tabKey = tabs.routes[tabs.index].key;
  const scenes = navigation[tabKey];
  return {
    scenes,
    tabKey,
    tabs,
  };
};

const mapStateToProps = (state) => {
  return {
    appNavigationState: getCurrentNavigation(state.navigation),
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    navigate: (action) => {
      if (action.type === 'pop') {
        dispatch(pop());
      } else if (action.type === 'push' && action.route) {
        dispatch(push(action.route));
      } else if (action.type === 'tab' && action.tabKey) {
        dispatch(selectTab(action.tabKey));
      }
    }
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(Navigator);

actions.js

export function pop() {
  return ({
    type: 'POP_ROUTE',
  });
}

export function push(route) {
  return ({
    type: 'PUSH_ROUTE',
    route,
  });
}

export function selectTab(tabKey) {
  return ({
    type: 'SELECT_TAB',
    tabKey,
  });
}

reducer.js( 注意:我在這里使用不可變,但是你可以使用任何適合你的東西

import { NavigationExperimental } from 'react-native';
import { Record } from 'immutable';

const {
  StateUtils: NavigationStateUtils,
} = NavigationExperimental;


export const InitialState = Record({
  // Tabs
  tabs: {
    index: 0,
    routes: [
      { key: 'tab1' },
      { key: 'tab2' },
      { key: 'tab3' },
    ],
  },
  // Scenes
  tab1: {
    index: 0,
    routes: [{ key: 'tab1' }],
  },
  tab2: {
    index: 0,
    routes: [{ key: 'tab2' }],
  },
  tab3: {
    index: 0,
    routes: [{ key: 'tab3' }],
  },
});
const initialState = new InitialState();


export default function navigation(state = initialState, action) {
  switch (action.type) {
    case 'POP_ROUTE': {
      const tabs = state.get('tabs');
      const tabKey = tabs.routes[tabs.index].key;
      const scenes = state.get(tabKey);
      const nextScenes = NavigationStateUtils.pop(scenes);

      if (scenes !== nextScenes) {
        return state.set(tabKey, nextScenes);
      }
      return state;
    }

    case 'PUSH_ROUTE': {
      const route = action.route;
      const tabs = state.get('tabs');
      const tabKey = tabs.routes[tabs.index].key;
      const scenes = state.get(tabKey);
      const nextScenes = NavigationStateUtils.push(scenes, route);

      if (scenes !== nextScenes) {
        return state.set(tabKey, nextScenes);
      }
      return state;
    }

    case 'SELECT_TAB': {
      const tabKey = action.tabKey;
      const tabs = state.get('tabs');
      const nextTabs = NavigationStateUtils.jumpTo(tabs, tabKey);

      if (nextTabs !== tabs) {
        return state.set('tabs', nextTabs);
      }
      return state;
    }

    default:
      return state;
  }
}

最后,在MyScene.js組件中,您可以通過測試當前路徑(例如,使用開關)來簡單地處理要顯示的組件。 通過在組件中傳遞導航功能,您可以管理場景(即:this.props.navigate({type:'push',route:{key:'search'}}))。

請注意,您可以根據需要處理您的州和您的行為。 理解的主要思想是如何減少狀態,無論你是否使用redux。

我建議你使用react-navigation進行原生和web環境,它將取代NavigationExperimental ,看看下面的例子

  • 為iOS和Android構建的組件
  • 在移動應用程序,Web應用程序和服務器呈現之間共享導航邏輯。
  • 文檔非常簡單
  • 開發自己的導航視圖
  • 這很容易!

只需在您的應用中定義導航即可。

import {
  TabNavigator,
} from 'react-navigation';

const BasicApp = TabNavigator({
  Main: {screen: MainScreen},
  Setup: {screen: SetupScreen},
});

......並導航

class MainScreen extends React.Component {
  static navigationOptions = {
    label: 'Home',
  };
  render() {
    const { navigate } = this.props.navigation;
    return (
      <Button
        title="Go to Setup Tab"
        onPress={() => navigate('Setup')}
      />
    );
  }
}

並執行以下操作以添加redux,只需定義您的reducer ...

const AppNavigator = StackNavigator(AppRouteConfigs);

const appReducer = combineReducers({
  nav: (state, action) => (
    AppNavigator.router.getStateForAction(action, state)
  )
});

...並使用addNavigationHelpers在組件中addNavigationHelpers

  <AppNavigator navigation={addNavigationHelpers({
    dispatch: this.props.dispatch,
    state: this.props.nav,
  })} />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM