javascript best - React-Native-Custom navigation with Navigator component




example react-native-navigation (5)

I'm exploring possibilities of React Native while developing a demo app with custom navigation between views with the help of Navigator component - http://facebook.github.io/react-native/docs/navigator.html#content

The main app class renders navigator and inside renderScene returns passed component:

class App extends React.Component {
    render() {
        return (
            <Navigator
                initialRoute={{name: 'WelcomeView', component: WelcomeView}}
                configureScene={() => {
                    return Navigator.SceneConfigs.FloatFromRight;
                }}
                renderScene={(route, navigator) => {
                    // count the number of func calls
                    console.log(route, navigator); 

                    if (route.component) {
                        return React.createElement(route.component, { navigator });
                    }
                }}
             />
        );
    }
}

For now app contains 2 views:

class FeedView extends React.Component {
    render() {
        return (
            <View style={styles.container}>
                <Text>
                    Feed View!
                </Text>
            </View>
        );
    }
}

class WelcomeView extends React.Component {
    onPressFeed() {
        this.props.navigator.push({
            name: 'FeedView',
            component: FeedView
        });
    }

    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>
                    Welcome View!
                </Text>

                <Text onPress={this.onPressFeed.bind(this)}>
                    Go to feed!
                </Text>
            </View>
        );
    }
}

What I want to figure out is -

  • I see in logs that when pressing "go to feed" renderScene is called several times though the view renders correctly once. Is it how the animation works?

    index.ios.js:57 Object {name: 'WelcomeView', component: function}
    index.ios.js:57 Object {name: 'FeedView', component: function}
    // renders Feed View
    
  • Generally does my approach conforms the React way, or it can be done better?

What I want to achieve is something similar to NavigatorIOS but without navigation bar (however some views will have their own custom navigation bar).


Answers

Your approach should work great. In big apps at Fb, we avoid calling the require() for the scene component until we render it, which can save a bit of start-up time.

The renderScene function should be called when the scene is first pushed to the Navigator. It will also be called for the active scene when the Navigator gets re-rendered. If you see renderScene get called multiple times after a push, then it is probably a bug.

The navigator is still a work in progress, but if you find any problems with it please file on github and tag me! (@ericvicenti)


As others have previously mentioned, Navigator has been deprecated since v0.44, but can still be imported to support older applications:

Navigator has been removed from the core React Native package in version 0.44. The module has been moved to a react-native-custom-components package that can be imported by your application in order to maintain backwards compatibility.

To see the original docs for Navigator, please switch to an older version of the docs.

As per the docs (React Native v0.54) Navigating Between Screens. It is now recommended to use React Navigation if you are just getting started, or NavigatorIOS for non-Android applications

If you are just getting started with navigation, you will probably want to use React Navigation. React Navigation provides an easy to use navigation solution, with the ability to present common stack navigation and tabbed navigation patterns on both iOS and Android.

...

If you're only targeting iOS, you may want to also check out NavigatorIOS as a way of providing a native look and feel with minimal configuration, as it provides a wrapper around the native UINavigationController class.

NB: At the time of providing this answer, React Native was at version 0.54


Navigator is deprecated now in RN 0.44.0 you can use react-native-deprecated-custom-components instead to support your existing application that is using Navigator.


Navigator component is deprecated now. You could use react-native-router-flux by askonov, it has a huge variety and supports many different animations and is efficient


The React-Native documentation has a brief section on approaches to communicating between components.

When you're trying to do something more complicated than a parent->child or child->parent relationship, there are a few options:

  1. Manager pattern. For true sibling<->sibling communications (i.e. where the two siblings share a parent via composition), you can have the parent manage the state. For example, you might have a <MyConsole> widget that has a <TextInput> and a <ListView> containing the past inputs by a user, both are children of the <Console> widget.

    • Here, the <Console> can act as a manager. When the <TextInput>changes its value, you can use the onChangeText event to pass the new value up to the parent <MyConsole> component, which then updates its state and passes that onto its children.
  2. Event (publish-subscribe) pattern. Remember that components are just objects, and so you can use object oriented approaches to communicating between components. The React documents note that:

    For communication between two components that don't have a parent-child relationship, you can set up your own global event system. Subscribe to events in componentDidMount(), unsubscribe in componentWillUnmount(), and call setState() when you receive an event.

    • Here, you can use a simple publish-subscribe library like pubsub.js so that when one component changes it just publishes the change and other related components can listen for the event and update themselves. This can be a very effective approach for smaller apps.
  3. Flux pattern. One of the drawbacks with a pure publish/subscribe system is, it becomes difficult to keep track of state. For example, if you have 2 components (e.g. EditTitle, EditBody) which can both update some state like an email message, then a pure eventing system ends up passing different versions of state around which can get messy with conflicts because there is no "single version of the truth". This is where React's flux approach comes in. With flux, components update a data store which is responsible for updating and reconciling data (e.g. EmailDataStore), and the store then notifies components of the updated state.

    • So in your example, the task view would issue an update (e.g. via publish, or direct function invocation) to a TasksDataStore, which might then publish an event like tasks-updated to its subscribers. Both the tasks panel and the results panel would subscribe to the data store.

When setting up subscriptions, it's best to add subscriptions after the component mounts and definitely remove them before the component unmounts (otherwise you end up with a lot of orphaned subscriptions).





javascript ios navigation reactjs react-native