1

1. Custom routing

As we all know, whether in native Android or iOS, they have a default routing routing stack management class. Since React Native does not officially provide routing management components, we need to use the Stack.Navigator component provided by the react-navigation plugin to manage routing.

The named route used by Stack.Navigator, the so-called named route, means that the route needs to be declared before it can be used. In order to facilitate the management of the routing page, we will put the routing in a unified location, such as the screens package, as shown below.
在这里插入图片描述

Then, we create a new constant in the screens/index.js file of the project, which is mainly used to manage the declared routes, as shown below.

export const stacks = [
  {
    name: 'AllMovieScreen',
    component: AllMovieScreen,
    options: {headerShown: false},
  },
  {
    name: 'CitySelectScreen',
    component: CitySelectScreen,
    options: {title: '选择城市'},
  },
  …. //省略其他路由页面
];

Then, we create a new MainStackScreen.js file to implement routing jump, return and other operations. At the same time, another function of the MainStackScreen class is to unify the style of the navigation bar. The code is shown below.

onst MainStack = createStackNavigator();

function MainStackScreen({navigation}) {
  return (
    <MainStack.Navigator
      initialRouteName="App"
      screenOptions={{
        headerTitleAlign: 'center',
        headerStyle: {
          shadowOffset: {width: 0, height: 0},
          shadowColor: '#E5E5E5',
          backgroundColor: '#fff',
        },
        gestureEnabled: true,
        headerBackTitleVisible: false,
        headerLeft: () => (
          <TouchableOpacity
            onPress={() => navigation.goBack()}
            style={{padding: 10, paddingRight: 30}}>
            <Icon name="chevron-thin-left" size={20} color="#222222" />
          </TouchableOpacity>),
      }}>
      <MainStack.Screen
        name="App"
        component={BottomTab}
        options={{headerShown: false}}/>
      {stacks.map((item, index) => (
        <MainStack.Screen
          key={index.toString()}
          name={item.name}
          component={item.component}
          options={item.options}/>
      ))}
    </MainStack.Navigator>
  );
}

export default MainStackScreen;

In the above code, we created a creens/index.js file to declare the route of the application, and then use the map loop in the MainStackScreen class to complete the route registration. As you can see, after the above processing, the routing management is very clear. When there is a new page, you only need to add the routing to the creens/index.js file.

2. Tab navigation

In React Native application development, in addition to providing routing management functions, react-navigation also supports Tab navigation and Drawer navigation. And, in the latest version, the libraries that Tab navigation, Drawer navigation and Stack navigation rely on are separate, so they need to be installed separately during the development process.

For Tab navigation, you need to install the bottom-tabs library required for Tab navigation in the project. The command is as follows.

npm install @react-navigation/bottom-tabs    

The createBottomTabNavigator() method is needed when creating Tab navigation. It needs to provide two properties of navigator and routing, corresponding to the two components of Tab.Navigator and Tab.Screen, and finally need to wrap them with the NavigationContainer component, as shown below.

import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {NavigationContainer} from '@react-navigation/native';

const BottomTabs = createBottomTabNavigator();

export default function BottomTabScreen() {
  return (
    <NavigationContainer>
      <BottomTabs.Navigator
        initialRouteName="Home"
        screenOptions={({route}) => ({
          tabBarIcon: ({focused}) => {
            return (
              <Image source={ focused? tabImage[`${route.name}_active`]
                    : tabImage[route.name]
                }
                style={{width: 26, height: 26}}/>
            ); }})}
        tabBarOptions={{
          activeTintColor: 'tomato',
          inactiveTintColor: 'gray',
          style: {
            backgroundColor: '#fff',
          },
        }}>
        <BottomTabs.Screen
          name="Home"
          component={HomeScreen}
          options={{
            tabBarLabel: '电影',
          }}/>
         
…. //省略其他代码

        <BottomTabs.Screen
          name="Mine"
          component={MineScreen}
          options={{
            tabBarLabel: '我的',
          }}/>
      </BottomTabs.Navigator>
    </NavigationContainer>
  );
}

At the same time, the bottom-tabs plug-in also provides many other useful components and attributes, developers can choose according to their needs. Run the above code, the effect is shown in the figure below.
在这里插入图片描述

3. Data return

Sometimes, we have such a requirement: Jump to the next page, and return the data after selecting the data on the next page. for example:
在这里插入图片描述

In the above scenario, we need to filter the activity list. After jumping to the activity filtering page, we need to return the selected activity type. For this scenario, what do we need to do with react-navigation?

First, we register the activity type page in the screens/index.js file as shown below.

{
  name: 'SelectorScreen',
  component: SelectorScreen,
  options: nav => {
    const {route} = nav;
    const {params = {}} = route;
    const {title = '活动类型', onRightPress = () => {}} = params;
    return {
       title,
       headerRight: () => (
         <TouchableOpacity
            onPress={onRightPress}
            style={styles.button}>
            <Text style={{color: '#fff', fontSize: 14}}>确定</Text>
         </TouchableOpacity>
        ),
      };
    },
  }

At the same time, the data of the activity screening page is passed from the activity list page. So when you use it, you only need to use the routing tool encapsulated above to perform the jump operation. The code is as follows.

navigate('SelectorScreen', {
      values: categories.map(c => c.andGroupName),
      defaultValues: categoryName,
      onConfirm: changeCategory,
    });

As you can see, in order to obtain the data selected by the filter page, we define an onConfirm callback function when jumping. Then, we can receive the activity data passed from the previous page on the newly created activity filter page and use the list to display it, as shown below.

function SelectorScreen({navigation, route}) {
  const {values = [], defaultValues = [], onConfirm} =route.params || {};
  const [selected, setSelected] = useState(defaultValues);

  const _onRightPress = () => {
    onConfirm(selected);
    navigation.goBack();
  };

  useEffect(() => {
    navigation.setParams({onRightPress: _onRightPress});
  }, [selected]);

  const onPressItem = val => {
    let arr = [];
arr = [val];  
setSelected(arr);
  };

  const renderItem = ({item}) => {
    const renderRight = () => {
    const isSelected = selected.includes(item);
    return (
      <ListItem
        text={item}
        renderRight={renderRight}
        onPress={() => onPressItem(item)} />
    );
  };

  return (
    <View style={styles.bg}>
      <FlatList
        keyExtractor={(item, index) => item + index}
        data={values}
        renderItem={renderItem}
        ListFooterComponent={<View height={120} />} />
    </View>
  );
};

const styles = StyleSheet.create({
 …. //省略样式代码
});

export default SelectorScreen;

After selecting the activity type, how to return the selected result to the previous page? At this time, the onConfirm callback function defined above is used, as shown below.

const {values = [], defaultValues = [], onConfirm} =route.params || {};

const _onRightPress = () => {
    onConfirm(selected);        //onConfirm回调函数回传数据
    navigation.goBack();
 };

xiangzhihong
5.9k 声望15.3k 粉丝

著有《React Native移动开发实战》1,2,3、《Kotlin入门与实战》《Weex跨平台开发实战》、《Flutter跨平台开发与实战》1,2和《Android应用开发实战》