Arpith Siromoney 💬

Two Steps to Navigation in React Native

I’m building an app called Constellational to make posting notes online fun. Sign up here if that sounds interesting. Today I added a navigation page to move between your drafts, the posts that you’re currently editing, and all your posts. There are basically two steps to navigation in React Native.

Switch between components based on route

In my index.ios.js I used Navigator to switch between pages:

class Constellational extends React.Component {
 renderScene(route, nav) {
   switch (route.id) {
     case 'welcome':
       return <WelcomePage navigator={nav} />;
     case 'navigation':
       return <NavPage navigator={nav} />;
     case 'posts':
       return <PostsPage navigator={nav} filter={route.filter} />;
     default:
       return <EditPage route={route} navigator={nav} />;
   }
 }
 render() {
   SettingStore.loadSettings();
   return (<Navigator
     initialRoute=
     renderScene={this.renderScene}
     configureScene={() => Navigator.SceneConfigs.FloatFromRight}
   />);
 }
}
AppRegistry.registerComponent('Constellational', () => Constellational);

Push a new Route to the Navigator

I then used a ListView to list the navigation options, which are basically filters for the posts that are displayed:

class PostsPage extends React.Component {
 constructor(props, context) {
   super(props, context);
   var dataSource = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
   this.getAll = this.getAll.bind(this);
   this.renderRow = this.renderRow.bind(this);
   this.state = {
     options: dataSource.cloneWithRows(this.getAll())
   };
   this.onChange = () => {
     this.setState({
       options: dataSource.cloneWithRows(this.getAll())
     });
   };
 }
  componentDidMount() {
   PostStore.addChangeListener(this.onChange);
   DraftStore.addChangeListener(this.onChange);
   EditStore.addChangeListener(this.onChange);
 }

 componentWillUnmount() {
   PostStore.removeChangeListener(this.onChange);
   DraftStore.removeChangeListener(this.onChange);
   EditStore.removeChangeListener(this.onChange);
 }
  getAll() {
   var list = ['All Posts'];
   if (!EditStore.isEmpty()) list.push('Currently Editing');
   if (!DraftStore.isEmpty()) list.push('Drafts');
   list.push('Help');
   return list;
 }
  render() {
   return (
     <View style={styles.page}>
       <Text>Constellational</Text>
       <ListView
         automaticallyAdjustContentInsets={false}
         dataSource={this.state.options}
         renderRow={this.renderRow}
       />
     </View>
   );
 }

 renderRow(filter) {
   var onPress = () => this.props.navigator.push({id: 'posts', filter: filter});
   return <Text onPress={onPress}>{filter}</Text>;
 }
}

That looks like a lot of code, but it’s basically checking if the flux stores have drafts or posts that are currently being edited before adding those options to the list. When an option is chosen, a new route is pushed to the navigator with an id — which was what was used by index.ios.js to decide which page to switch to — and the filter.

That’s about it! You can view the code that displays the posts here, and read about it here. This also fixes #54.