Giter VIP home page Giter VIP logo

react-navigation's Issues

Nested Navigators in Redux

Hello,

I'm trying to set up a TabNavigator inside a StackedNavigator, sort of like this:

TabsNavigator = TabNavigator({
            HomeScreen: {
                screen: HomeScreen,
                navigationOptions: {
                    tabBar: () => ({
                        label: 'Home'
                    })
                }
            },
            MyAction: {
                screen: Settings,
                navigationOptions: {
                    tabBar: () => ({
                        label: 'Settings'
                    })
                }
            },
        }, {
            tabBarPosition: 'bottom',
            animationEnabled: true,
            swipeEnabled: true
        });
        ModalNavigator = StackNavigator({
            Home: {
                screen: TabsNavigator
            }
        });

My issue is, since I'm using Redux, I can pass the outer StackedNavigator the nav state easily enough:

import { ModalNavigator } from '../scenes';
const AppNavigatorWithRedux = connect()(ModalNavigator);
<AppNavigatorWithRedux
         navigation={navigation}
/>

But I don't know how to pass the TabNavigator's state down to it. I'm assuming right now I'm going to have to wrap it in another component and get my other navigation state, but is there another/simpler way?

My reducer is:

import { ModalNavigator, TabsNavigator } from '../scenes';
const navReducer = (state, action) => {
    return {
        ModalNavigator: ModalNavigator.router.getStateForAction(action, state),
        TabNavigator: TabNavigator.router.getStateForAction(action, state)
    };
};

const appReducer = combineReducers({
    navReducer,
    mainReducer
});

Support React Elements as header title

People will want to use images, custom fonts etc for the title. So we should allow react elements too

static navigationOptions = {
  header: {
    title: React.Element<*>
  }
}

Move addNavigationHelpers functions to an action creators file

When using with Redux we have to manually create the objects to dispatch:

dispatch({ type: 'Navigate', routeName: 'Home' });

This make us dependent on the type string value key.

I took a look the source code and found that addNavigationHelpers.js have the so called Action creators.

It might me helpful to move those functions to a separate file and include them on addNavigationHelpers.js but also expose them to be imported on custom reducers.

export const navigate = (routeName, params, action) => ({
  type: 'Navigate',
  routeName,
  params,
  action,
});

// ...

Posible usage on custom reducers:

import * as actions from 'react-navigation/actions';

function reducer(state = initialState, action) {
  switch (action.type) {
    case LOGIN_SUCCESS:
      return AppNavigator.router.getStateForAction(actions.navigate('Home'), state); 
   default:
      return AppNavigator.router.getStateForAction(action, state);
  }
}

Docs: Contribution Guide / Submitting / New views -> Incomplete

New views or unique features

Often navigation needs are specific to certain apps. If your changes are unique to your app, you may want to fork the view or router that has changed. You can keep the source code in your app, or publish it on npm as a react-navigation compatible view or router.
This library is intended to include highly standard and generic navigation patterns. But it

It looks like the New views section is incomplete and just ends at the noted bolded section

Drawer + nested StackNavigator issue

Hello there,
first of all thank you for creating react-navigation, let's hope it become the standard for the react-native navigation.

I'm trying to migrate to react-navigation an application (that was previously using ex-navigation) and I'm having some issues.

The app navigation follows a common flow: There is an authentication screen, if the user is authenticated he can access the "core" of the app, where there is a DrawerNavigator and where each drawer route is a StackNavigator.

I tried to implement the app this way (feel free to tell my I'm dumb if i'm wrong):

1. The first stack
The first screen is a splash screen, it initializes the app and (almost instantly) redirect the user to an authentication screen or to the main screen.
I handled this with a StackNavigator:

const AppStackNavigator = StackNavigator({
  SplashScreen: { screen: SplashScreen },
  AuthScreen: { screen: AuthScreen }, // User not logged in
  MainDrawerNavigator: { screen: MainDrawerNavigator } // User logged in
}, {
  headerMode: 'screen'
})

In SplashScreen I'll do some stuff and then redirect the user to AuthScreen or to MainDrawerNavigator by resetting the stack (this is the only way to reset the stack at the moment, am I right?):

this.props.navigation.dispatch({
   type: 'Reset',
   index: 0,
  actions: [{ type: 'Navigate', routeName: 'MainDrawerNavigator' }]
})

2. The drawer navigator
If the user is authenticated he can access MainDrawerNavigator, which contains the "core" of the application, and navigate through all the app using the drawer. Each drawer link is a stack navigator.

const MainDrawerNavigator = DrawerNavigator({
  ApplianceStackNavigator: { screen: ApplianceStackNavigator },
  SettingStackNavigator: { screen SettingStackNavigator }
}, {
  initialRouteName: 'ApplianceStackNavigator',
  headerMode: 'screen'
})

3. The stack navigator sub-routes

const ApplianceStackNavigator = StackNavigator({
  ApplianceListScreen: { screen: ApplianceListScreen },
  NewApplianceScreen: { screen: NewApplianceScreen }
}, {
  initialRouteName: 'ApplianceListScreen',
  headerMode: 'screen'
})

And here is where the issue arises.
When I'm inside one of the drawers sub-routes (Appliance/Setting) the navigation doesn't work correctly.
For example, if I'm in the the ApplianceListScreen and I want to go to the NewApplianceScreen using this.props.navigation.navigate('NewApplianceScreen') I'm expecting that the route gets pushed, but instead the stack is reset (resetted?) to it.


TLDR: Using a StackNavigator as a DrawerNavigator route doesn't seems to work correctly: the routes don't get pushed correctly.


I know that this lib is super-young, and that my issue description might be a bit of a mess, but thank you in advance anyway :)
P.S.: I wanted to create a repo to show the problem but I discovered this issue while working on a work-related-project and publishing the repo would mean re-writing all the code because I'm on NDA (still, I can setup a dummy repo in the next days if it is needed).

P.P.S: The entire app entry point is the following:

const ApplianceStackNavigator = StackNavigator({
  ApplianceListScreen: { screen: ApplianceListScreen },
  NewApplianceScreen: { screen: NewApplianceScreen }
}, {
  initialRouteName: 'ApplianceListScreen',
  headerMode: 'screen'
})

const MainDrawerNavigator = DrawerNavigator({
  ApplianceStackNavigator: { screen: ApplianceStackNavigator }
}, {
  initialRouteName: 'ApplianceStackNavigator',
  headerMode: 'screen'
})

const AppStackNavigator = StackNavigator({
  SplashScreen: { screen: SplashScreen },
  AuthScreen: { screen: AuthScreen },
  MainDrawerNavigator: { screen: MainDrawerNavigator }
}, {
  headerMode: 'screen'
})

export default class SlowdiveLoveReact extends Component<void, void, void> {
  render () {
    return (
      <View style={styles.container}>
        <Provider store={store}>
          <AppStackNavigator />
        </Provider>
      </View>
    )
  }
}

How to change right component or title of header depending on component state or props?

First thanks guys for this library!
It's super easy to understand unlike others navigation libraries.
Screen (component) can change its state or props can be changed.
I tried to setParams in componentWillUpdate and other lifecycle methods and then change "right" and "title" in navigationOptions but it invoked only one time.

Sorry if I asked a dumb question.
Thanks in advance.

How to disable the left-to-right transition animation during initial app launch?

I use TabNavigator and here's the full code:

class HomeScreen extends React.Component {
    render() {
        return <View style={{flexDirection:'row', backgroundColor: 'red', height: 300,
            justifyContent:'flex-end', paddingTop: 30}}>
            <Text>Hello, Navigation!</Text>
        </View>
    }
}

class SecondScreen extends React.Component {
    render() {
        return <View style={{flexDirection:'row', justifyContent:'flex-end', paddingTop: 30}}>
            <Text>Hello, Second!</Text>
        </View>
    }
}

const AppContainer = TabNavigator({
        HomePage: {screen: HomeScreen},
        SecondPage: {screen: SecondScreen}
    }
)

As you can see, when app initially launches, the text "flies" in ... How can I disable this effect?

jan-27-2017 14-00-02

Thanks in advance!

StatusBar should be a configurable screen option

Each screen should be able to set properties on the device's status bar, and the container defined in createNavigationContainer should get the options on state change, and apply them natively.

Documentation: Differences from `NavigationExperimental`

First of all, congrats on the release. Everything looks great and is overall well documented.

One thing I think is missing are documented reasons why this would be a better option than using the built-in NavigationExperimental library that is actively being developed on the react-native side.

For example, my team is using NavigationExperiemental on the react-native side and react-router on the web side. Is the primary gain by using this new react-navigation library that you can share all navigation logic between both?

I'd be happy to issue a PR documenting this if I just had a better understanding. Thanks for your time.

Play nicely with translucent StatusBar on Android

In Expo we use a translucent StatusBar by default on Android, and some normal React Native projects may do this as well because it makes it easier to reason about cross-platform since the iOS StatusBar is always translucent.

We may need to upstream a constant to React Native that we can use to check if the StatusBar is translucent, and then add any necessary paddingTop to the navigation bar when it is.

router.getScreenConfig is broken

Currently the second argument received by a navigation options item is the previous config returned from a parent navigation options, and the options passed to getScreenConfig.

IMO it's a confusing behaviour, because fundamentally they are different types of objects, one is the configuration for navigator, other is arbitrary options the navigator can pass to the configuration function. For example, the tab navigator can provide a focused argument for the icon, which doesn't make sense in a config.

The way this works is, only the global navigator config receives the options passed to the getScreenConfig, and it has to explicitly merge it with, say, header config and return it. Which means if you have a static header configuration for screens, and then add a header configuration at the global level to be used as default, it breaks the screen configuration because it doesn't receive the options anymore and you've to explicitly merge the options in the global navigator config. Same for the route navigation config, which will break if you add a screen config.

image

Personally I think the confusing behaviour and the learning curve associated with it is not worth getting rid of one extra function.

global config - the navigationOptions passed in the second argument to the navigator
screen config - the static navigationOptions in the screens
route config - the navigationOptions specified for individual routes in the first argument to the navigator

Flow types for both,

type NavigationOptionItem<T> =
  | T
  | (navigation: NavigationScreenProp<*,*>, T) => T

type IconOptions = {
  focused: boolean;
  tintColor: boolean;
}

These are the current api and the proposals we discussed:

Current API

Options is the result of previous header function/previous header object

header: (navigation, options) => ({
  ...options,
  icon: ({ focused, tintColor }) => <Icon name={'settings' + focused ? '' : '-outline'} color={tintColor} />
});

Flow type,

type HeaderOptionItem = NavigationOptionItem<{
  title: string;
  icon: IconOptions => React.Element<*>;
}>

How it is used,

const { icon } = router.getScreenConfig(...);
return icon({ focused, tintColor });

Pros

  • router.getScreenConfig doesn't deal with options passed to icon, so it's pretty generic, navigators can do whatever they want
  • the icon function can be declared inline, so much simpler to use
  • we can support both function and plain element, so no one needs to use a function if not needed

Cons

  • Function inside object inside function, though it's function inside object if you don't need the outer function

Proposed API #1

Options is the result of previous header function/previous header object merged with params passed to getScreenConfig

header: (navigation, options) => ({
  ...options,
  icon: <Icon name={'settings' + options.focused ? '' : '-outline'} color={options.tintColor} />
});

Flow type,

type HeaderOptionItemConfig = {
  title: string;
  icon: React.Element<*>;
}

// not sure if `HeaderOptionItemConfig & ?IconOptions` is valid, but wanted to denote that the merged object may or may not contain icon options even if the navigator always passes it
type HeaderOptionItem = NavigationOptionItem<HeaderOptionItemConfig & ?IconOptions>

How it is used,

return router.getScreenConfig(.., { focused, tintColor }).icon;

Pros

  • Only two arguments to learn

Cons

  • Automatically merging 2 different kinds of objects can be confusing, for example focused doesn't make sense inside navigationOptions.header. For some things like tintColor, it could be irrelevant if tintColor might make sense in the config, but see next one for that
  • getScreenConfig has to handle the options, limited to objects only
  • What takes precedence? navigationOptions or the params passed to getScreenConfig? Can I override the other?

Proposed API #2

Options is the result of previous header function/previous header object

header: (navigation, options) => ({
  ...options,
  activeTintColor: 'orange',
  inactiveTintColor: 'blue',
  activeIcon: <Icon name='settings' color='blue' />,
  inactiveIcon: <Icon name='settings-outline' color='orange' />
});

Flow type,

type HeaderOptionItem = NavigationOptionItem<{
  title: string;
  activeTintColor: string;
  inactiveTintColor: string;
  activeIcon: React.Element<*>;
  inactiveIcon: React.Element<*>;
}>

How it is used,

return router.getScreenConfig(..).activeIcon;
return router.getScreenConfig(..).inactiveIcon;

Pros

  • router.getScreenConfig doesn't deal with options passed to icon

Cons

  • I can configure the colors of text with activeTintColor, but for the icon, I have to type it again, and I made a typo
  • I have to write almost similar component twice, can make it a function to simpify, but then it's no better than current API where I can use a function, and even write it inline
  • This assumes that the navigator doesn't need to pass options, and this assumption will likely break in future

Proposed API #3

Previous result is the result of previous header function/previous header object

header: (navigation, params, previousResult) => ({
  ...previousResult,
  icon: <Icon name={'settings' + params.focused ? '' : '-outline'} color={params.tintColor} />
});

Flow type,

type NavigationOptionItem<T, U> =
  | T
  | (navigation: NavigationScreenProp<*,*>, T, U) => T

type HeaderOptionItem = NavigationOptionItem<{
  title: string;
  icon: React.Element<*>;
}, IconOptions>

How it is used,

return router.getScreenConfig(.., { focused, tintColor }).icon;

Pros

  • No automatic merging between incompatible types

Cons

  • 3 arguments to learn (should be an object most prolly)
  • getScreenConfig has to handle the options, limited to objects only, e.g. - getScreenConfig(..., () => {}) is not possible (likely not a significant issue)

cc @skevy @mkonicek

Render Drawer on top of menu

It would be nice if we could optionally (or by default) render the drawer on top of the header rather than underneath it if the DrawerNavigator is nested. Let's say I have the following routes:

const MainNavigator: any = DrawerNavigator({
  Dashboard: { screen: Scenes.Dashboard },
  Log: { screen: Scenes.Log },
}, {
  initialRouteName: 'Dashboard',
});

const AppNavigator: any = StackNavigator({
  Main: { screen: MainNavigator },
  Login: { screen: Scenes.Login },
  Password: { screen: Scenes.Password },
}, {
  initialRouteName: loggedIn ? 'Main' : 'Login',
});

Currently, the problem is if you are on the Dashboard screen, the drawer opens up underneath the header. It's acceptable for most routes, but I have some screens that render a transparent header and it looks odd when the drawer renders underneath it.

Thanks!

Question: calling navigate on top level component

assume we have this component.
how can i trigger navigate event from the top level of App component?
in this example lets say under someEvent function.
this event is for top level (like new push notification arrived) and not per each individual loaded screen so it has to happen in App class.

const AppNavigator = StackNavigator(SomeAppRouteConfigs);

class App extends React.Component {
  someEvent() {
    // call navigate for AppNavigator here?
  }
  render() {
    return (
      <AppNavigator />
    );
  }
}

Accessibility Review

Before being prod-ready, we need to make sure a11y features work well on both platforms.

Android back button behavior

Is there a plan to introduce the same component that is in ex-navigation for this purpose? Thanks a lot for this lib!

What I have in mind is that the android back button "just works" while it can be overridden like this i.e. not worrying about it but having the ability to control what happens when the back button on android is pressed, if needed.

use case: I need to select some items from a list, and on android, the back button takes me out of the "selection mode", similar to selecting mail in gmail app.
1

Make it possible to pass `style` to header

As Martin suggested in old repo, it would be great to have an ability to define a custom style for a header on a Navigator level.

This is already getting implemented in #1. As a follow-up, we will expose style.

Help: Navigate from nested navigation

Hi all, I am trying to setup navigation in my app but having some trouble navigating from nested views. Im pretty sure im doing this wrong since I cant go from a 2nd level view to another 2nd level view in another Navigator.

Basically I want to go from LoginView to MainView somehow but keeping WelcomeNavigator separate from HomeNavigator (mostly for organization purposes but also to clear the stack when transitioning from !isLoggedIn screen to isLoggedIn screen)

Can someone point me in the right direction? Thanks!

const WelcomeNavigator = StackNavigator({
  Login: { screen: LoginView},
  Register: { screen: RegisterView}
}, {
  headerMode: 'none'
});

const HomeNavigator = TabNavigator({
  Main: {screen: MainView },
  Settings: { screen: SettingsView}
});

const MasterNavigator = StackNavigator({
  Welcome: { screen: WelcomeNavigator },
  Home: { screen: HomeNavigator }
},
{
  headerMode: 'none'
});

How to run the examples?

As far as I know we have to first init a clean RN project and then add react-navigation via yarn or npm to the new project.

If I got it right, we then have to navigate in the new project folder to node_modules/react_navigation and do the steps described here:

https://github.com/react-community/react-navigation/tree/master/examples/NavigationPlayground

cd react-navigation
npm install
cd examples/NavigationPlayground
npm install
cd ../..
react-native start
cd examples/NavigationPlayground
react-native run-ios # ignore packager starting error
react-native run-android # ignore packager starting error

But if I do this, I get: 'Android project not found' even with two separate shells.

How do we run the examples on the correct way?

Am I the only one?

Various prop types are missing

From the code, there are a bunch of places where prop types are used, but not indicated in other places.

  • screenProps -> apparently these can be passed down, but there's little indication
  • making a custom header; StackNavigator passes in HeaderComponent to CardStack but CardStack doesn't seem to do anything with it

state not available

Hi,

I have an issue trying to open a detail screen.

In my routing config, I have this:

const Navigator = DrawerNavigator({
    Details: {
        path: 'details/:pk',
        screen: DetailsContainer
    }
    [...]
});

In some Component, I navigate like this:

navigation.navigate('Details', {pk: 1})

In the Detail Component, I don't have navigation.state:

console.log(navigation)
=> {key: "Details", routeName: "Details"}

Any idea what I'm doing wrong?

Is it possible to style toolbar(header) now?

Can't find any api for this purpose. Something like in react-native-navigator:

{
  navBarTextColor: '#000000', // change the text color of the title (remembered across pushes)
  navBarBackgroundColor: '#f7f7f7', // change the background color of the nav bar (remembered across pushes)
  navBarButtonColor: '#007aff', // change the button colors of the nav bar (eg. the back button) (remembered across pushes)
  navBarHidden: false, // make the nav bar hidden
  navBarHideOnScroll: false, // make the nav bar hidden only after the user starts to scroll
  navBarTranslucent: false, // make the nav bar semi-translucent, works best with drawUnderNavBar:true
  navBarTransparent: false, // make the nav bar transparent, works best with drawUnderNavBar:true,
  topBarElevationShadowEnabled: false, // Android only, default: true. Disables TopBar elevation shadow on Lolipop and above
  navBarNoBorder: false, // hide the navigation bar bottom border (hair line). Default false
  drawUnderNavBar: false, // draw the screen content under the nav bar, works best with   navBarTranslucent:true
}

Can't display element on the left side of the header

Main: {
  screen: MainScreen,
  navigationOptions: {
    header: {
      left: <Button title="Back" />,
    },
  },
}

Nothing shows when I try to display an element on the left side of the header (but it does with right). Could this not be supported yet by any chance?

Reset action does not seem to work

I'm trying to reset the stack in a StackNavigation using:

        dispatch({
            type: 'Reset',
            actions: [{
                type: 'Navigate',
                routeName: 'Home',
            }],
        })

However, this gives an error: "There should always be only one scene active, not 0".

If I try to dispatch() the reset action, followed by a navigate(), then it works but it does not "forget" any part of the history stack. How can I reset the stack?

[TabNavigator] : Bad Output Range

I get this error when i want render navigator

screen shot 2017-01-28 at 7 31 42 pm

Here is my code

import { TabNavigator } from 'react-navigation';
import * as screens from 'AppScreens';

const configure = {};

for (const name in screens) {
	if (!screens.hasOwnProperty(name)) {
		continue;
	}
	configure[name] = {
		screen: screens[name]
	};
}

const options = {
	tabBarOptions: {
    activeTintColor: '#e91e63',
  },
}
export const Navigator = TabNavigator(configure, options);

export const App = () => (
	<Provider store={store}>
		<Navigator />
	</Provider>
);

Help: How to perform navigation in header left or right elements

Hi,

I'd like to ask for an example of invoking .navigate from with the left or right elements of a header. Something along the line of

header: ({ state, setParams }) => {
   // The navigation prop has functions like setParams, goBack, and navigate.
   let right = (
     <Button
       title="Options"
       onPress={() => this.props.navigation.navigate('Options')}
     />
   );
   return { right };
 },

where Options is another screen. The above doesn't work. I'm missing how to get hold of the navigation object.

Thanks

Library and examples probably not ready for use with Windows

Got the following output on

'npm install' within the react-navigation folder...

'rm' is not recognized as an internal or external command. [...]

Win 7
npm v 4.1.2
node v 6.9.4

PS:
Tried to hint this issue with rimraf in package.json, but then the install breaks at
cannot read property split of undefined at compile-docs.js.

I'm wondering seeing so much 'Mac-first approaches' in React land.
Shouldn't traditional MS Windows dev-environments supported from the beginning?

https://gist.github.com/domenic/2790533

Header for DrawerNavigator

Thanks for the awesome work on this library!

I'd like to use the classical header with a hamburger pattern in combination with the DrawerNavigator but I can't figure out how to do so apart from manually including the header in every screen where I want it rendered, which seems a bit redundant. Is that actually how I should do it or is there a better way?

An example including a header would be much appreciated. Examples of StackNavigator nested behind DrawerNavigator would be nice too.

How do I add content above a top tab bar?

Hey, thanks for the release! I have a screen in my app that has some content that takes up about a third of the top of the screen, and below that I want to have a nested tab view with the tab bar just below the other content at the top. With ex-navigation it was simple to render the <SlidingTabNavigation> component below the rest of my component contents, but I can't figure it out with this library. It seems as I define my nested navigators as screens in a parent navigator, I don't know where I would even define that other content? Do I need to write a custom navigator?

Thanks for the help!

TabNavigator's tabs are not displayed when nested in a DrawerNavigator

Hi,

First, thank you for this module !

I have an issue when using a TabNavigator nested in a DrawerNavigator: tabs are not displayed.
This issue appears only when I go to the nested TabNavigator from the Drawer menu link and when using navigate('MyNestedTabStack') like in the get started guide.

Here is an example:

class HomeScreen extends React.Component {
    render() {
        return <Button
            onPress={() => this.props.navigation.navigate('Projects')}
            title="Go to Projects"
        />;
    }
}

class RecentProjectsScreen extends React.Component {
    render() {
        return <Text>List of recent projects</Text>
    }
}

class AllProjectsScreen extends React.Component {
    render() {
        return <Text>List of all projects</Text>
    }
}

const ProjectScreenNavigator = TabNavigator({
    Recent: { screen: RecentProjectsScreen },
    All: { screen: AllProjectsScreen },
});


const App = DrawerNavigator({
    Home: { screen: HomeScreen },
    Projects: { screen: ProjectScreenNavigator }
});

AppRegistry.registerComponent('App', () => App);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.