React Native + Redux:什么是最好的和首选的导航

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

本文关键字:导航 Native Redux 什么 React      更新时间:2023-09-26

我想在React Native中使用Redux。目前我没有设置数据管理,所以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导航的最佳方式是什么?使用store、reducers和actions的示例将非常有帮助。

现在应该使用react-navigation来代替NavigationExperimental。

,

我建议你使用NavigationExperimental而不是Navigator。最后一种是贬值的。在RN文档中有一个例子,就在这里。它使用简单的reducer来管理你的导航状态。但是你也可以用Redux处理这种状态,因为它是相同的逻辑。

这是我的选项卡设置,使用Redux和NavigationExperimental:

navigator.js(注意:CardStack中的renderOverlay道具在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组件中,你可以简单地通过测试当前路由来处理要显示的组件(例如使用开关)。通过在你的组件中传递 navigation 函数,你可以管理你的场景(例如:this.props)。导航({类型:"推",路线:{关键:"搜索 ' } })).

请注意,您可以按照自己的意愿处理状态和操作。要理解的主要思想是如何减少状态,无论您是否使用redux。

我建议你在本地和web环境中使用react-navigation,它将取代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

在组件中导航
  <AppNavigator navigation={addNavigationHelpers({
    dispatch: this.props.dispatch,
    state: this.props.nav,
  })} />