cannot readd property push of undefined - react-native

I am trying to put together my first app using react-native-navigation and I am taking pieces from the available examples on the web site.
Anyway, I am now trying to use a push function to have a new screen displayed, but the navigator seems to be undefined:
the structure is:
- app.js
- firstScreenTab
- pushScreenTab
- secondScreenTab
The navigator is obviously defined in the app.js file.
In my firstScreenTab:
testNavPress() {
this.props.navigator.push({
screen: 'manager.SecondTabScreen',
title: 'Pushed Screen'
});
}
<Button onPress={this.testNavPress.bind(this)}>
Push
</Button>
`
I set up my app using redux, I am wondering how should I pass my navigator as prop?
The start app function in my app.js looks like this:
startApp(root) {
console.log(root);
console.log('START APP!!!!!');
const tabs = [
{
label: 'Employees', // tab label as appears under the icon in iOS (optional)
screen: 'manager.EmployeeListScreen', // unique ID registered with Navigation.registerScreen
icon: require('../img/one.png'), // local image asset for the tab icon unselected state (optional on iOS)
selectedIcon: require('../img/one_selected.png'), // local image asset for the tab icon selected state (optional, iOS only. On Android, Use `tabBarSelectedButtonColor` instead)
iconInsets: { // add this to change icon position (optional, iOS only).
top: 6, // optional, default is 0.
left: 0, // optional, default is 0.
bottom: -6, // optional, default is 0.
right: 0 // optional, default is 0.
},
title: 'Employee List', // title of the screen as appears in the nav bar (optional)
navigatorStyle: {}, // override the navigator style for the tab screen, see "Styling the navigator" below (optional),
navigatorButtons: {
rightButtons: [
{
icon: require('../img/navicon_add.png'), // for icon button, provide the local image asset name
id: 'add' // id for this button, given in onNavigatorEvent(event) to help understand which button was clicked
}
]
} // override the nav buttons for the tab screen, see "Adding buttons to the navigator" below (optional)
},
{
label: 'One', // tab label as appears under the icon in iOS (optional)
screen: 'manager.FirstTabScreen', // unique ID registered with Navigation.registerScreen
icon: require('../img/one.png'), // local image asset for the tab icon unselected state (optional on iOS)
selectedIcon: require('../img/one_selected.png'), // local image asset for the tab icon selected state (optional, iOS only. On Android, Use `tabBarSelectedButtonColor` instead)
iconInsets: { // add this to change icon position (optional, iOS only).
top: 6, // optional, default is 0.
left: 0, // optional, default is 0.
bottom: -6, // optional, default is 0.
right: 0 // optional, default is 0.
},
title: 'Screen One', // title of the screen as appears in the nav bar (optional)
navigatorStyle: {}, // override the navigator style for the tab screen, see "Styling the navigator" below (optional),
navigatorButtons: {} // override the nav buttons for the tab screen, see "Adding buttons to the navigator" below (optional)
},
{
label: 'Two',
screen: 'manager.SecondTabScreen',
icon: require('../img/two.png'),
selectedIcon: require('../img/two_selected.png'),
title: 'Screen Two'
}
];
switch (root) {
case 'user':
Navigation.startTabBasedApp({
tabs,
tabsStyle: {
tabBarButtonColor: 'white',
tabBarSelectedButtonColor: 'white',
tabBarBackgroundColor: '#099880'
}
});
break;
default:
Navigation.startSingleScreenApp({
screen: {
screen: 'manager.LoginScreen', // unique ID registered with Navigation.registerScreen
title: 'Log in', // title of the screen as appears in the nav bar (optional)
navigatorStyle: {}, // override the navigator style for the screen, see "Styling the navigator" below (optional)
navigatorButtons: {} // override the nav buttons for the screen, see "Adding buttons to the navigator" below (optional)
}
});
}
} // startApp
}
export default App;
I browsed other questions but most of them refer to react-navigation, I am using react-native-navigation.

Navigation.startTabBasedApp doesn't use a navigator - it simply invokes a native method that constructs the UI according to the object you've provided.
Make sure you call super(props) in firstScreentab so RNN can inject the navigator into your screen.

Related

How to change the styling of the NativeBase Toast component's close IconButton?

I cannot find a way to change the style the IconButton of the status: 'error' Toast component in native base v3, which under the hood is using an IconButton component.
Here is the link to the main Toast functions such as useToast and their props
The simplified code to render a toast looks like the following:
import { useToast } from 'native-base';
...
const Toast = useToast():
...
Toast.show({
title: 'title',
status: 'error',
style: { backgroundColor: 'blue.200' },
})
But how would I increase the padding of the close icon button for example? It would be nice to do something like
I understand I can use the render prop to render a custom component, but I would prefer to use the default styling from native base and my extended theme - instead of having to style and render a component that looks exactly the same as the current Toast. This poses an issue if there are default style changes from native base or the app's extended theme, as changes would have to be hardcoded and changed in this render fn as well. Which is not practical!
Toast.show({
style: {
_icon: {
padding: 10,
},
}
// or
iconButtonStyle: { padding: 10 },
})
I can extend the theme and set a default style for IconButton component like so, but this would change every single IconButton in the app - which is not practical.
const myTheme = extendTheme({
components: {
IconButton: {
baseStyle: {
rounded: 'full',
padding: 10,
},
},
...
Is it possible to change the base styles like so?
const myTheme = extendTheme({
components: {
Toast: {
baseStyle: {
_icon: {
padding: 10,
},
},
},
...
It would be great to know how to change the styling of either:
the icon button of one specific Toast component (like in toast.show() above)
or the default styling for the close icon button of all Toast's, but not other IconButtons
Thanks!

Change bottom bar selected icon color dynamically on react-native-navigation

I'm using Wix's react-native-navigation (v1) and I wanted to change the selected state color depending on the current tab selected.
Now, there's a way to change it globally through tabBarSelectedButtonColor but I was wondering if there could be a chance of updating this variable color depending on the screen the user is in. i.e: Home will be green when selected, Tab2 will be blue and Tab3 will be red.
Creating the navigation like this:
Navigation.startTabBasedApp({
tabs: [
{
screen: 'screenName',
label: 'Home',
icon: iconsMap['md-home'],
navigatorStyle: {
navBarHidden: true
},
// this applies for other screens ofc
],
tabsStyle: {
forceTitlesDisplay: true,
tabBarTextFontFamily: 'fontname',
tabBarSelectedButtonColor: 'red'
},
appStyle: {
tabBarSelectedButtonColor: 'red'
}
});
Do you guys know a way to update it? or is there any callback function when the tab was pressed? So I could manually update it through there?
Thanks.

Is it possible to change react stack navigator pan gesture direction per screen?

I am using react navigation library and I would like root stack view to be able to push some screens using right to left animation and some screens bottom to top. The main problem I have encountered is pan gesture for dismissing screens remains the same for all screens.
My routes:
const MODAL_ROUTES = [
SceneKeys.EditProfileNavigator,
SceneKeys.PicturePreview
]
const navigator = createStackNavigator(
{
[SceneKeys.Main]: { // MAIN TAB BAR SCREEN
screen: Main,
},
// Profile edit - comes from bottom, should not be dismissable by gestures
[SceneKeys.EditProfileNavigator]: {
screen: EditProfileNavigator,
navigationOptions: {
gesturesEnabled: false,
}
},
// Picture preview - comes from bottom, should be dismissible with gesture top to bottom
[SceneKeys.PicturePreview]: {
screen: PicturePreview,
},
// comes from right, should be dismissible by swiping from the left
[SceneKeys.Conversation]: {
screen: Conversation
}
},
{
headerMode: 'none',
transitionConfig: (transitionProps, prevTransitionProps) => {
const isModal = MODAL_ROUTES.some(
screenName =>
screenName === transitionProps.scene.route.routeName ||
(prevTransitionProps && screenName === prevTransitionProps.scene.route.routeName)
)
return StackViewTransitionConfigs.defaultTransitionConfig(
transitionProps,
prevTransitionProps,
isModal
)
}
},
)
Animations and transitions all work fine, however the main problem is that PicturePreview screen can be dismissed using left to right pan gesture - I want top to bottom pan gesture dismissal for this screen in particular.
Setting whole stack mode to modal makes Conversation screen transition from bottom, when I want right to left transition
Not the answer that I was looking for, but I found solution to my problem.
Basically i wrapped my navigator to another modal navigator.
My Routes now look like this:
> Modal Stack navigator
> Stack navigator
> Tab Bar
> Conversation
> Edit profile
> Picture preview
Honestly if anyone wants to suggest how to fix my problem in other ways - please do

React Navigation: Prevent multiple instances to navigate to same screen

Let's say I have this screen:
And when the user clicks on the white tooltip, it redirects to another screen. Sometimes the app lags a little bit, and clicking on the tooltip takes like ~2s to see the screen change. The problem is, during those 2s, the user taps again on this tooltip to make it happen.
And the result I get is that there are two instances of the new screen in my StackNavigator. What I mean is that I see my new screen, but when I click on "Back" I don't return to this 'Hitchhiking Map' screen, but to another instance of that same screen.
If I clicked 5 times on the callout during those 2s, then I need to click 5 times "Back" to return to the Map screen. Any way to prevent that? To put only one instance into the StackNavigator?
I am using React Navigation, more precisely a StackNavigator. Here's my code:
The "click on tooltip" part:
<MapView.Marker
onCalloutPress={() => this.props.navigation.navigate('spotDetails', { spotId: marker.id })}
/>
My screens:
const HMapNavigator = StackNavigator({
HMap: { screen: HMapViewContainer },
spotDetails: { screen: SpotDetailsViewContainer },
});
The issue of multiple navigations has been reported and there is more detail here.
react-navigation (v1.0.0-beta.7) is in beta and still being built, so until this feature is implemented, you will have to handle the debounce manually.
options
disable the button once the navigation starts
debouncing in the onPress logic or in the action if you are using redux
lodash provides a useful debounce utility, if you are looking for one.
There are many ways how to overcome double navigations.
My solution is adding a key property in navigate object:
this.props.navigation.navigate({ key: 'AnotherScreen', routeName: 'AnotherScreen', params: { ... }})}
Save if its opening to control the navigation
constructor (props) {
super(props)
this.state = {
opening: false
}
}
Create a function to control de navigation
_open (campaign) {
if (!this.state.opening) {
this.props.navigation.navigate('Campaign', {campaign})
this.setState({ opening: true })
setTimeout(() => {
this.setState({ opening: false })
}, 1000)
}
}
Call this func from your onpress
<TouchableHighlight underlayColor='transparent' onPress={this._open.bind(this, campaign)}>
In versions 1.x of React Navigation, if you specify an identifier the navigation action will be executed only once. E.g.:
navigate({ routeName: 'someScreen', key: 'someScreen', params: { someParam: 'someValue' } })
More information: https://gist.github.com/vonovak/ef72f5efe1d36742de8968ff6a708985
In versions 2.x and 3.x this is a default functionality.
More info: https://reactnavigation.org/docs/en/navigation-key.html

Sencha Touch SetActiveItem adds Icon to TabBar

I have a fairly simple Sencha Touch MVC app where I have some main tabs (containing lists) driven by a tab bar. When the user taps on a list item I open a new panel using SetActiveItem. This seems ok but it adds an icon (or the empty clickable space) to the tab bar. How can I stop this?
My viewport:
app.views.Viewport = Ext.extend(Ext.TabPanel, {
fullscreen: true,
layout: 'card',
cardSwitchAnimation: 'slide',
initComponent: function() {
// put instances of cards into app.views namespace
Ext.apply(app.views, {
myList: new app.views.MyList(),
myDetail: new app.views.MyDetail()
...
});
//put instances of cards into viewport
Ext.apply(this, {
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
items: [
app.views.myList,
...
]
});
app.views.Viewport.superclass.initComponent.apply(this, arguments);
}
});
I then have a controller that fires on an item tap in my list:
app.views.viewport.setActiveItem(
app.views.myDetail,
options.animation
);
The panel opens but adds to the tabbar as well.
I'd appreciate any pointers!
What you need to do is change the layout of myList and the other tabPanel items to card layout, and call setActiveItem in the context of myList.
When you call setActiveItem directly on the TabPanel, this is the result that you get ( another item being added to the tabBar).
Besides, you don't need to set the layout to card in the TabPanel as it is already card layout by default.
The inner items (myDetail for example) should have a fit layout.