react-native Navigator.NavigationBar - where are the docs? - react-native

I've seen a few examples online using Navigator.NavigationBar. It looks handy but I don't know how to use it. Are there docs anywhere?

Officially there is no guide Navigator.Navigation Bar. But looking on the internet you can find examples of how it works. Below is an example that I used for one of my projects.
var PageOne = require('./pageone'),
PageTwo = require('./pagetwo');
var NavigationBarRouteMapper = {
LeftButton: function( route, navigator, index, navState ){
return(
<Text>{ route.leftButton }</Text>
)
},
Title: function( route, navigator, index, navState ){
return(
<Text>{ route.title }</Text>
)
},
RightButton: function( route, navigator, index, navState ){
return(
<Text>{ route.rightButton }</Text>
)
}
}
var App = React.createClass({
renderScene: function( route, nav ) {
switch (route.id) {
case 'PageOne':
return <PageOne navigator={ nav } title={ "PageOne" } />
case 'PageTwo':
return <PageTwo navigator={ nav } leftButton={ "Back" } title={ "PageTwo" } />;
}
},
render: function() {
return (
<Navigator
initialRoute={{ id: 'PageOne', title: 'PageOne' }}
renderScene={ this.renderScene }
configureScene={( route ) => {
if ( route.sceneConfig ) {
return route.sceneConfig;
}
return Navigator.SceneConfigs.FloatFromRight;
}}
navigationBar={
<Navigator.NavigationBar
routeMapper={ NavigationBarRouteMapper }
/>
}
/>
);
},
});

Updates on 2017: Official documentation of React Native recommend using react-navigation library.
Setup variable:
import {
StackNavigator,
} from 'react-navigation';
const App = StackNavigator({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
});
Example:
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigate } = this.props.navigation;
return (
<Button
title="Go to Jane's profile"
onPress={() =>
navigate('Profile', { name: 'Jane' })
}
/>
);
}
}
Read the official documentation for detailed information.

I would also add to checkout the UI Explorer in the examples that show how to use it. UIExplorer Navigator -
EDIT: React native has done a good job updating their docs. Here is the documentation to the navigator: navigator docs
UPDATE: Do your self a favor and use something like react-navigation. Those links will be broken because of MANY updates to RN.

Related

make dynamic tab on createMaterialTopTabNavigator of react-navigation

I'm making the top tab navigator using createMaterialTopTabNavigator of react-navigation. The problem I faced is that the tabs have to decide by the response data of API request. For example, I call an API to request the football team list, receive the list and then set the tabs of the MaterialTopTabNvigator.
I already make the label of the navigator using the component like following :
class TabBarLabel extends React.Component {
constructor(props) {
super(props);
}
render() {
return this.props.focused ? (
<View style={lstyles.container_focused}>
<Text style={lstyles.label_focused}>{this.props.name}</Text>
</View>
) : (
<View style={lstyles.container_blur}>
<Text style={lstyles.label_blur}>{this.props.name}</Text>
</View>
);
}
}
const FootballTeamNavigator = createMaterialTopTabNavigator(
{
teamA : {
screen: AScreenComponent,
navigationOptions: () => {
return {
title: 'teamA',
tabBarLabel({focused}) {
return <TabBarLabel focused={focused} name="teamA" />;
}
};
}
}
},
{
initialRouteName: teamA,
swipeEnabled: false,
timingConfig: {
duration: 1000,
},
tabBarOptions: {
scrollEnabled: true,
...styles,
},
},
);
What I want to do is like :
let teamList = {};
apiForGetFootballTeamList().then(response => {
for (const team of response.data.list) {
tempList[team.name] = team;
}
});
createMaterialTopTabNavigator(
{
...teamList
},
{
initialRouteName: ...,
...
}
);
But I don't know how can I update the tabs using data, like component. (component has state and if we update the state, the component is updated)
Is there any way for it?
Current versions of React Navigation don't support dynamic configuration. You need to use React navigation 5 for that https://blog.expo.io/announcing-react-navigation-5-0-bd9e5d45569e
Got to a couple of different threads trying to do this (this one among others). Did not manage to find a solution, but in the end it ended up being rather easy.
<Tab.Navigator>
{villages.map(village => (
<Tab.Screen
key={village.villageId}
name={village.name}
component={ResourceFieldScreen}
initialParams={{ village: village }}
/>
))}
</Tab.Navigator>
At the top, before the function itself I have:
const Tab = createMaterialTopTabNavigator();
In this case screens are created based on how many counts of village there are in villages. Then a prop of village is sent to the component that is supposed to render it all ResourceFieldScreen. Which makes it possible to show whatever is included in villages, on that screen.
Code for that part:
function ResourceFieldScreen({ route }) {
const village = route.params.village;

Passing Navigator object in renderItem

I'm struggling to make Navigator object visible in List Component.
Here the code explained: as you can see in RootDrawer, I have Concept component. It simply shows a list of items based on a id passed in param.
Each item points to another Concept with another id, but I get
undefined is not an object (evaluating 'navigation.navigate')
when I press on that <RippleButton> with onPress={() => navigation.navigate('Concept',{id:12}). The problem here I'm not passing the Navigation object correctly. How can I solve?
main Navigator drawer
const RootDrawer = DrawerNavigator(
{
Home: {
screen: StackNavigator({
Home: { screen: Home }
})
},
Search: {
screen: StackNavigator({
Cerca: { screen: Search },
Concept: { screen: Concept },
})
}
}
);
Concept component
export default class Concept extends Component {
loading = true
static navigationOptions = ({ navigation,state }) => ({
headerTitle: "",
title: `${navigation.state.params.title}` || "",
})
constructor(props) {
super(props);
}
async componentDidMount(){
}
render() {
const { params } = this.props.navigation.state;
const id = params ? params.id : null;
const { t, i18n, navigation } = this.props;
const Concept = DB.get(id)
return (
<View>
<ScrollView>
<List data={Concept.array|| []} title={"MyTile"} navigation={navigation} />
</ScrollView>
</View>
);
}
}
List Component
class List extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
const { navigation } = this.props;
}
_renderItem = (item,navigation) => (
<RippleButton
id={item.id}
onPress={() => navigation.navigate('Concept', { id: 12, otherParam: 'anything you want here'})}> //this line throws the error
<Text>{item.Term}</Text>
</RippleButton>
)
render() {
const { navigation } = this.props;
return (
<View>
<FlatList
data={this.props.data}
renderItem={({item}) => this._renderItem(item, navigation)}
/>
</View>)
}
}
Instead of passing the navigation prop, you can try using the withNavigation HOC.
Where your List Component is defined:
import { withNavigation } from 'react-navigation`
....
export default withNavigation(List)
Now the List component will have access to the navigation prop

How to pass parameters from parent activity to child tabs in react native?

I am new in react native and looking if someone could direct me in detail how to pass parameters to a child tab.
I researched already and found that it could be done using screenprops, however none of those gave me a clear understanding on how to use it to pass the parameters. A clean sample code could be beneficial.
It is quite easy you have not look around enough there are lots of packages, I recommend you to use following package, and take a look at following example. Next time research information that you need before you ask something.
import React, { Component } from 'react';
import { TabView, TabBar, SceneMap } from 'react-native-tab-view';
import SceneA from './SceneA';
import SceneB from './SceneB';
class Layout extends Component {
constructor(props) {
super(props);
this.state = {
index: 0,
routes: [
{ key: 'active', title: 'Scene A' },
{ key: 'inactive', title: 'Scene B' },
],
};
this.renderScene = this.renderScene.bind(this);
this.renderLabel = this.renderLabel.bind(this);
this.onTabChange = this.onTabChange.bind(this);
}
onTabChange(index) {
this.setState({ index });
}
// Here you can send props to different tab components
renderScene({ route }) {
if (!route.key) return null;
if (route.key === 'active') {
return <SceneA type="active" />; // SceneA specific props here
}
if (route.key === 'inactive') {
return <SceneB type="inactive" />;
}
}
renderLabel({ route }, props) {
const { index } = this.state;
const selected = route.key === props.navigationState.routes[index].key;
return (
<View>
<Text>
{route.title.toUpperCase()}
</Text>
</View>
);
}
renderTab() {
return (
<TabView
navigationState={this.state}
onIndexChange={this.onTabChange}
renderScene={this.renderScene}
renderTabBar={props => (
<TabBar
{...props}
renderLabel={e => this.renderLabel(e, props)}
/>
)}
/>
);
}
render() {
return (
<View>
{this.renderTab()}
</View>
);
}
}
export default Layout;

In a React-Native app, how to use SwitchNavigator (react-navigator) and react-redux?

I'm using react-navigation's SwitchNavigator to manage my navigation based on authentication state. When Authenticated, I want to use Redux to store data I'm fetching.
My SwitchNavigator looks like this
SwitchRouteConfig = {
AuthLoading: AuthLoadingScreen,
Authenticated: AppStackNavigator,
NotAuthenticated: AuthStackNavigator,
}
SwitchConfig = {
initialRouteName: 'AuthLoading',
}
export default createSwitchNavigator(SwitchRouteConfig, SwitchConfig);
My Authenticated navigation looks like this:
// App Bottom Tab Navigator
const AppTabRouteConfig = {
AddItem: { screen: AddItem },
Items: { screen: Items },
Map: { screen: Map },
Help: { screen: Help },
}
const AppTabConfig = { initialRouteName: 'Items',}
const AppTabNavigator = new createBottomTabNavigator(
AppTabRouteConfig,
AppTabConfig)
And in my Screen we have:
class Items extends React.Component {
constructor(props){
super(props);
this.state = {};
}
componentDidMount(){
this.props.getData(); //call our redux action
}
render() {
if(this.props.isLoading){
return(
<View>
<ActivityIndicator />
</View>
)
} else {
return (
<Provider store={store}>
<SafeAreaView>
<FlatList
data={this.props.dataSource.features}
renderItem={({ item }) =>
<TouchableWithoutFeedback>
<View style={styles.listContainer}>
<Text>{item.prop1}</Text>
<Text>{item.prop2}</Text>
</View>
</TouchableWithoutFeedback>
}
/>
</SafeAreaView>
</Provider>
)
}
}
}
function mapStateToProps(state, props) {
return {
isLoading: state.dataReducer.isLoading,
dataSource: state.dataReducer.dataSource
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(Actions, dispatch);
}
export default connect(mapStateToProps,
mapDispatchToProps)(Items)
When I'm not authenticated, that works fine. I can login. When I am authenticated, I get the following error:
Invariant Violation: Could not find "store"
in either the context or props of
Connect(Items)". Either wrap the root
component in a <Provider>, or explicitly pass
"store" as a prop to "Connect(Items)".
In the reading I've done today, all the samples have a single top-level component which they wrap with . So, I'm not understanding how you instantiate the store and manage Redux without that model.
I should mention two additional things:
The initial authenticated app screen worked fine before I started to implement Redux.
I'm not trying to manage the state with Redux, just application data.
Project started with Create-React-Native-App.
Thank you!
You have to wrap the root component (the switch navigator) inside Provider to make the store available to all container components.
const SwitchRouteConfig = {
AuthLoading: AuthLoadingScreen,
Authenticated: AppStackNavigator,
NotAuthenticated: AuthStackNavigator,
}
const SwitchConfig = {
initialRouteName: 'AuthLoading',
}
const Navigator = createSwitchNavigator(SwitchRouteConfig, SwitchConfig);
// You can use a stateless component here if you want
export default class Root extends React.PureComponent {
render() {
return (
<Provider store={store}>
<Navigator />
</Provider >
);
}
}

Howto pass data to a other component with react native Navigator

i'm using a Navigator component and want to pass data from a component to a other.
here is some code.
renderScene(route, navigator) {
var routeId = route.id;
if (routeId === 'SplashPage') {
return (
<SplashPage
navigator={navigator} />
);
}
if (routeId === 'Login') {
return (
<Login
navigator={navigator} />
);
}
if (routeId === 'Home') {
return (
<Home
navigator={navigator} />
);
}
....
I want to pass data from login to home when i click on a button for example
this.props.navigator.replace({
id: 'Home',
passProps: {
currentUser: this.user,
}
})
i would like to get the currentUser in the Home Component. I've tried some code that i found but nothing seem to work.
This is whant i want to do :
class Home extends React.Component {
constructor(props){
super(props);
this.currentUser = ????????
}
If anyone can help me with this i would be grateful.
Thanks
You can set up your renderScene method like this:
renderScene={(route, navigator) => {
return React.createElement(route.component, { ...this.props, ...route.passProps, navigator, route } );
}}
And use it like this:
this.props.navigator.replace({
component: Home,
passProps: {
currentUser: this.user,
}
})
And in Home, you can access currentUser like this:
<Text>{ this.props.currentUser }</Text>
Check out this thread for a more detailed example, but that should work for you.