I was using RNN V1 and decided to update to the latest since I needed more customization, it updated to the V3-alpha. Don't know if this was a mistake from my part or not, if I prolly should go to latest V2 for more stability.
Thing is, whenever I start my project on a different mac, it throws the following error:
Exception 'Bridge not yet loaded! Send commands after Navigation.events().onAppLaunched() has been called.' was thrown while invoking setDefaultOptions on target RNNBridgeModule with params (
{
statusBar = {
style = light;
visible = 1;
};
topBar = {
visible = 0;
};
},
30,
31
)
callstack: (
The only place where i set the setDefaultOptions was when starting the tab based navigation.
This is the code for that.
import { Navigation } from 'react-native-navigation';
import { iconsMap } from '../../_global/AppIcons';
import i18n from '../../_global/i18n';
import { navigatorStyle } from '../../styles/navigatorStyles';
Navigation.setDefaultOptions({
statusBar: {
visible: true,
style: 'light'
},
topBar: {
visible: false
}
});
const startTabs = () => {
Navigation.setRoot({
root: {
bottomTabs: {
animate: true,
visible: false,
drawBehind: true,
elevation: 8,
children: [
{
stack: {
children: [
{
component: {
id: 'MainTab',
name: 'app.MainTab'
}
}
],
options: {
bottomTab: {
text: i18n.t('main'),
icon: iconsMap['home'],
...navigatorStyle
}
}
}
},
{
stack: {
children: [
{
component: {
id: 'MyProfileTab',
name: 'app.MyProfileTab'
}
}
],
options: {
bottomTab: {
text: i18n.t('myProfile'),
icon: iconsMap['md-person'],
...navigatorStyle
}
}
}
},
{
stack: {
children: [
{
component: {
id: 'MessageScreen',
name: 'app.MessageScreen'
}
}
],
options: {
bottomTab: {
text: i18n.t('messages'),
icon: iconsMap['comment-dots'],
badge: '2',
badgeColor: 'red',
...navigatorStyle
}
}
}
}
]
}
}
});
}
export default startTabs;
On my main macbook used to work, why is not working on a different computer? what could I be possibly be doing wrong or missing here? I got the latest code on both.
Even tried commenting out the setDefaultOptions but the error still shows up.
Any help will be appreciated.
The most likely option is how you are passing the default Options. Make sure you pass them inside registerAppLaunchedListener before Navigation.setRoot({}) option.
Navigation.events().registerAppLaunchedListener(() => { // here }.
So your code will look something like this.
Navigation.events().registerAppLaunchedListener(() => {
Navigation.setDefaultOptions({
//options here
})
Navigation.setRoot({
root: {
bottomTabs: {
//bottom tabs option
}
}
});
});
Related
I'm using Wix's react-native-navigation V3. I'd need to know if there's a way to call a function whenever Navigation.pop() is finished executing.
My specific case scenario is as follows.
I have 3 stack tab buttons, where I can push a new screen and pop back.
All works fine, except for the case that, from that pushed screen, I'd need to go to a different tab. If I mergeOptions directly to change currentTabIndex, the bottomTabs will disappear. Found out that I have to first, pop() and then mergeOptions.
Is there a way to accomplish this? When I run both in the same function, only pop() is triggered, I need to add some sync to this.
This is my current stack structure:
const startTabs = () => {
Navigation.setRoot({
root: {
bottomTabs: {
animate: true,
visible: false,
drawBehind: true,
elevation: 8,
waitForRender: true,
children: [
{
stack: {
id: 'MainTabStack',
children: [
{
component: {
id: 'MainTab',
name: 'app.MainTab'
}
}
],
options: {
bottomTab: {
text: i18n.t('home'),
icon: iconsMap['home-light'],
selectedIcon: iconsMap['home-solid'],
...navigatorStyle
}
}
}
},
{
stack: {
id: 'MyProfileTabStack',
children: [
{
component: {
id: 'MyProfileTab',
name: 'app.MyProfileTab'
}
}
],
options: {
bottomTab: {
text: i18n.t('myProfile'),
icon: iconsMap['user-light'],
selectedIcon: iconsMap['user-solid'],
...navigatorStyle
}
}
}
},
{
stack: {
id: 'MessageTabStack',
children: [
{
component: {
id: 'MessageScreen',
name: 'app.MessageScreen'
}
}
],
options: {
bottomTab: {
text: i18n.t('messages'),
icon: iconsMap['message-light'],
selectedIcon: iconsMap['message-solid'],
badgeColor: 'red',
...navigatorStyle
}
}
}
}
]
}
}
});
}
So I start from MainTab, then I push a new screen from this MainTab. Let's name it SingleViewScreen. When I'm done doing some stuff in SingleViewScreen, by an onPress function I need to pop() this current screen and go directly to MessageScreen.
Any ideas? Am I doing something wrong? Thanks.
You can use registerCommandCompletedListener
Invoked when a command (i.e push, pop, showModal etc) finishes executing in native. If the command contains animations, for example pushed screen animation, the listener is invoked after the animation ends.
Try this
// Subscribe
const commandCompletedListener = Navigation.events().registerCommandCompletedListener(({ commandId, completionTime, params }) => {
});
...
// Unsubscribe
commandCompletedListener.remove();
I am using React Native Navigation v2 from WIX in my RN project. For Dashboard(goToDahboard) stack I need to show hamburger icon on the left on on click show side drawer. How can this be implemented?
Since upgrading from v1, side menu options has changed and the docs aren't clear enough.
export const goToDashboard = () =>
Promise.all([
Icon.getImageSource('home', 22, '#272727'),
Icon.getImageSource('th-list', 22, '#272727'),
]).then(sources => {
Navigation.setRoot({
root: {
bottomTabs: {
children: [
{
stack: {
children: [
{
component: {
name: 'Dashboard',
},
},
],
options: {
bottomTab: {
icon: sources[0],
text: 'Dashboard',
},
},
},
},
{
stack: {
children: [
{
component: {
name: 'Settings',
},
},
],
options: {
bottomTab: {
icon: sources[1],
text: 'Settings',
},
},
},
},
],
id: 'bottomTabs',
},
},
});
});
export const goToAuth = () =>
Navigation.setRoot({
root: {
stack: {
id: 'Login',
children: [
{
component: {
name: 'Login',
},
},
],
},
},
});
I'am using like this, thats my code;
Navigation.setRoot({
root:{
sideMenu:{
left:{
component:{
name:'app.Main.SideDrawer'
}
},
center:{
bottomTabs:{
id: 'MainAppBottomTab',
children:[
{
stack:{
children:[
{
component:{
name: 'app.Main.Bottom_1',
options:{
bottomTab:{
text: "Bottom 1",
icon: require('./../../assets/images/Bottom_1.png'),
}
},
}
}
],
options: {
bottomTab: {
text: 'Bottom 1',
},
bottomTabs:{
backgroundColor: ColorTable.orange,
animate:false,
},
topBar:{
title:{
text: 'Bottom 1',
},
leftButtons:[
{
id: 'btn_toggle_drawer',
name: 'BTN_TOGGLE_DRAWER',
icon: require('./../../assets/images/hamburger_icon.png'),
}
],
}
}
}
}
]
}
}
}
}
});
Now we need to use wix's life cycle.
If you want to close it in SideDrawer, you should use the following code;
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
left: {
visible: false
}
}
});
this.props.componentId equal to app.Main.SideDrawer. Because of we are in app.Main.SideDrawer component.
If you want to open with hamburger icon, Go to whatever page you want to use for bottomTab, in our example I said Bottom_1.
Don't forget to type Navigation.events().bindComponent(this) into the constructor method. This allows you to linking with native.
Only the following command will work;
navigationButtonPressed({buttonId}) {
if (buttonId === "btn_toggle_drawer") {
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
left: {
visible: true
}
}
});
}
}
The code above works but is problematic. You're going to tell me that I'm going to have to press twice to turn it off =)
The solution is to use redux. Or mobx whichever you prefer.
To solve this problem, I used redux and redux-thunk.
Wix's is life cycle, please explore it: https://wix.github.io/react-native-navigation/#/docs/Usage?id=screen-lifecycle
With redux solution
Real function is;
navigationButtonPressed({buttonId}) {
if (buttonId === "btn_toggle_drawer") {
this.props.toggleDrawer(this.props.isSideDrawerVisible);
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
left: {
visible: this.props.isSideDrawerVisible
}
}
});
}
}
toggle_drawer action
export const toggleDrawer = (visible) => {
return (dispatch) => {
(visible) ? visible = true : visible = false;
dispatch({
type: TOGGLE_DRAWER,
payload: visible
});
}
};
toggle_drawer reducer
const INITIAL_STATE = {
isSideDrawerVisible: true
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case TOGGLE_DRAWER:
return {...state, isSideDrawerVisible: action.payload};
default:
return state;
}
}
Sample connect function;
import {connect} from "react-redux";
// actions
import {toggleDrawer} from "../../../actions/toggle_drawer";
const mapStateToProps = state => {
return {
isSideDrawerVisible: state.toggleDrawer.isSideDrawerVisible,
}
};
export default connect(mapStateToProps, {toggleDrawer})(Bottom_1_Screen);
Don't forget to connect wix with Redux. https://wix.github.io/react-native-navigation/#/docs/third-party?id=redux
I hope I can help you, I saw it a little late.
Have a nice day..
You can use
Navigation.mergeOptions()
like this to fire and open the drawer:
navigationButtonPressed = ({ buttonId }) => {
const { componentId } = this.props;
if (buttonId === 'sideMenu') {
Navigation.mergeOptions(componentId, {
sideMenu: {
left: {
visible: true,
},
},
});
}
}
I want side menu in a particular screen in stack navigation.
How can i navigation.push to a screen in stack navigation having a side menu in react native navigation v2. As Navigation.push only takes component object.
Navigation.setRoot({
root: {
stack: {
id: 'App',
children: [
{
component: {
name: 'FormList',
options: {
topBar: {
title: {
text: 'Forms'
}
}
}
}
}
],
}
}
});
I want to push to a screen in CreateForm which would have a sidemenu
const sidemenu = {
sideMenu: {
center: {
component: {
name: 'CreateForm',
options: {
topBar: {
title: {
text: 'Create Form'
},
},
}
},
},
right: {
component: {
name: 'CreateField',
passProps: {
text: ''
},
},
},
}
};
I have root screen that contains 4 bottoms tabs implemented using react-native-navigation, for one of my bottomtab having sub tabs(topTabs) so now how can I navigate to next screen from the current screen.(note: the next screen is not a registered screen in root)
please anyone help me
here is my root navigation
export const startNavigation = () => {
Navigation.setRoot({
root: {
sideMenu: {
left: {
component: {
name: screenName.DRAWER
}
},
center: {
bottomTabs: {
children: [{
stack: {
children: [{
component: {
name: screenName.Sample1
}
}],
options: {
bottomTab: {
text: 'Sample1',
}
}
}
}, {
stack: {
children: [{
component: {
name: screenName.HOME
}
}],
options: {
bottomTab: {
text: 'Home',
selectedTextColor: 'red'
}
}
}
}],
options: {
bottomTabs: {
currentTabIndex: 1
}
}
}
}
}
}
})
}
from this root, how I will navigate to sub tabs or sunscreens
Have you tried anything? can you post some code?
if you are getting started, here is the official documentation from React Native
https://wix.github.io/react-native-navigation/#/docs/Usage
I'm trying to call Navigate.push from sideMenu but nothing happens.
Navigation.setRoot({
root: {
sideMenu: {
left: {
component: {
name: 'app.SideMenu',
},
children: [
{
stack: {
children: [
{
component: {
name: TERMS_SCREEN.id,
}
},
]
}
}
]
},
center: {
bottomTabs: {
id: 'BottomTabsId',
options: {
topbar: {
visible: true,
}
},
children: [
{
stack: {
id: 'Tabs',
children: [
{
..and I'm trying to push a screen in sideMenu like this
console.log(this.props.componentId);
Navigation.push(this.props.componentId, {
component: {
name: 'app.Terms',
}
})
I am getting the log but nothing happens. I'm positive that I need to do something with my layout but I don't see an example or explanation in docs.
There's something wrong with how you structure the components in the menu. The issue is that you must have a stack to be able to push other screens, and from what it looks - this is not the case for your side menu screen.
This is how you would set a left sideMenu component which is a stack; once you do that, you'll be able to push screens exactly as you did with Navigation.push(this.props.componentId...:
left: {
stack: {
children: [
{
component: {
name: 'app.SideMenu',
}
}
]
}
}
What I was doing wrong is actually because I'm passing the sidemenu componentId when in fact I need to pass the id of the current tab. Something like this.
Navigation.push(`Tab${this.props.activeTabIndex + 1}`,{
component: {
name: Screens.ACCOUNTS,
}
}
)
also sidemenu layout is this
root: {
sideMenu: {
id: 'SideMenu',
left: {
component: {
id: 'SideMenu.left',
name: Screens.SIDEMENU,
}
},
while having children and stack in sidemenu object might be one solution. but you could do this as well. Consider following
Navigation.setRoot({
root: {
sideMenu: {
left: {
id: "AppSideMenu",
component: {
id: "HomeScreenDrawer",
name: "YO.HomeScreen.Drawer",
},
},
center: {
stack: {
id: "AppHomeStack",
children: [
{
component: {
id: "AppHomeScreen",
name: "YO.HomeScreen",
options: {
topBar: {
visible: false,
drawBehind: true,
height: 0,
},
statusBar: {
style: "light",
},
},
},
},
],
},
},
},
},
});
This way when you are going to push just call the ID of your main stack which lies under center{stack:{}} with ID of AppHomeStack
Now anywhere in the app, this will just do the trick
Navigation.push("AppHomeStack", {
component: {
name: "YO.UserScreen",
},
});