I am writing a project that navigates using react-navigation and i want to use lightbox however lightbox requires Navigator to function properly. I was hoping to see if i could write react-navigation support into the component and then allow a PR to happen. The possibility in my mind is using Navigator + react navigation so that i dont have to re-make my navigation because you could have both "this.props.navigator" and "this.props.navigation" but i am not sure how some of the navigation and navigator functions work.
I have been looking into lightbox.js at the occurences of Navigator and i am searching through the react-navigation api to see if i can find replacements for the functions used as it only occurs 8 times (2 of which are just checks to see if navigator is present).
lightbox.js - navigator occurences
open: function() {
this._root.measure((ox, oy, width, height, px, py) => {
this.props.onOpen();
this.setState({
isOpen: (this.props.navigator ? true : false),
isAnimating: true,
origin: {
width,
height,
x: px,
y: py,
},
}, () => {
if(this.props.navigator) {
create a route that will work with navigation (for react-navigation it would be the navigationOptions)
var route = {
component: LightboxOverlay,
passProps: this.getOverlayProps(),
};
fetch the current set of routes
var routes = this.props.navigator.getCurrentRoutes();
push a route onto the stack
routes.push(route);
some sort of reset for the stack that Navigator does (still looking into it, any help knowing what this does would be nice.
this.props.navigator.immediatelyResetRouteStack(routes);
Then the rest of the code for opening the lightbox runs
} else {
this.setState({
isOpen: true,
});
}
this.setTimeout(() => {
this.state.layoutOpacity.setValue(0);
});
});
});
},
for closing the stack the same lines are called but with .pop() instead of .push()
Anyone with experience of both react-navigation and react-native-lightbox would be a great help.
Related
https://wix.github.io/react-native-navigation/docs/basic-navigation#navigating-in-a-stack
indicates that pushing a new screen to the stack requires the current screen's componentId. My use case is to allow navigating based on certain events emitted by a native module. As such, componentId won't be available to me, since the event listener would reside outside any React component screen. Is there any way to navigate to a screen from outside in RNN? Or even get the current componentId.
I ended up adding a command event listener to store the current componentId in closure.
let currentComponentId;
Navigation.events().registerCommandListener((name, params) => {
if (name === 'push') {
currentComponentId = params.componentId;
}
});
Navigation.events().registerAppLaunchedListener(() => {
Navigation.setRoot(rootRouteConfig);
EventEmitter.addListener('navigate', (name) => {
Navigation.push(currentComponentId, {
component: {
name,
},
});
});
});
So i have an app with react native navigator, what I plan for my app is to show a Tutorial when the user first launches the app, I use react-copilot for it, it works really great, but the problem is, React copilot takes time to initiate, and it launches BEFORE the react-navigator.
The problem is that the user can click the navigator thus breaking the tutorial or even crashing the system because the tutorial did not initiate properly.
I plan to make the navigator to be disabled dynamically when the tutorial not yet started. Here's the snippet of the code from the navigationOptions on the appNavigation
TabMenu.navigationOptions = ({ navigation, screenProps }) => {
const childOptions = getActiveChildNavigationOptions(navigation, screenProps);
return {
title: childOptions.title,
tabBarVisible: childOptions.tabBarVisible,
header: null
};
};
and here's the static value on the component
static navigationOptions = {
tabBarVisible: false
}
It works, but the problem is when the tutorial ends and I set the static value to true, the tabBar doesn't appear. Is there any way around this?
Thank you in advance
EDIT :
i need to clarify that what i need is to make the tabbar appear and dissapear within the same page after certain activity (in this case tutorial) finished without the need to reload/navigate to the same page
It's like Gabriel answer
static navigationOptions = ({ navigation, screenProps }) => {
const { tabBarVisible = true } = navigation.state.params
? navigation.state.params
: {};
return {
tabBarVisible: tabBarVisible
};
};
Place the navigation options inside any Tab Item and update the tabBarVisible property like this.
this.props.navigation.setParams({
tabBarVisible: false
});
I would try putting all the tutorial from react-copilot into a different page which is not inside the bottom navigation bar or maybe even in a Modal (which by default cover the whole application).
After the react-copilot instructions are done you are free to navigate to the bottom navigation bar or dismiss the Modal.
NEW SUGGESTION AFTER COMMENT:
I think you could change some values in the navigationOptions by doing the following:
static navigationOptions = ({ navigation }) => {
return {
headerTitle: navigation.getParam('title', ''),
}
};
and then in a function inside the component calling the following:
this.props.navigation.setParams({ "title": 'brand new name') })
This works for me on an app where I had to change the header title of a page after a button was clicked. But I'm not sure if that would work with the attribute tabBarVisible. Would you mind giving it a try?
I think this is pretty straight forward when it comes to passing between screens of tab navigators but there seems to be a problem while trying to pass parameters from a tab navigator screen to a stack navigator screen in react-native using react-navigation.
I tried this:
onPress={() => {
this.props.navigation.navigate('review', {
aa1: 86,
bb1: 'anything you want here',
});
}}
And this:
onPress={() => this.props.navigation.dispatch(NavigationActions.navigate({ routeName: 'review', params: { aa1: 'x' }, }))}
as the onPress handler of my TouchableOpacity. None of them work. I can navigate but I can't get the params.
Below is how I try to get the parameters in the target stack navigator screen:
const { navigation } = this.props;
//if a is not passed, No a is the default value.
const a = this.props.navigation.getParam('aa1', 'NO a');
const b = navigation.getParam('bb1', 'No b');
Any ideas?
I was able to figure and solve the problem.
Problem was that name of the screen I was trying to navigate to and the name of the stack navigator (name of the stack navigator in the containing/parent tab navigator) that contained that screen was the same. And although navigation was working, the parameters were not being passed as I said in the problem description. Navigation was working because the screen that I was trying to navigate was set as the initial route in the containing stack navigator. Apparently, I was navigating and passing the parameters to the containing stack navigator. Once I changed the name of the stack navigator, the problem was solved.
Use navigation.push instead of navigation.navigate.
Reference: Oficial Docs.
I was facing the same problem, and i saw your own answer. The reason why this happens easily is that you are sending information to the stack, and not to the screens. As you can see in https://reactnavigation.org/docs/nesting-navigators, when you want to pass parameters to another screen inside a stack you need to specify the stack, then the screen and then the parameters, just like that:
navigation.navigate('Root', {
screen: 'Profile',
params: { user: 'jane' },
});
To be honest you can just put the parameters right with the screen, as in:
navigation.navigate('Root', {
screen: 'Profile',
user: 'jane',
});
I am using React navigation I am looking for a way to pass parameters into my navigation stack as follows. I have actually one screen which I want to use X amount of times. It only needs an url and a title, and based on the url it should do exactly the same for each url.
So i want to create an object like so:
const urls = {
{title: 'foo', url: 'https://someurl'},
{title: 'bar', url: 'https://someotherurl'}
}
And now in my Navigation component I would like to do something like:
export default createMaterialTopTabNavigator({
SomeKey: {
// Loop here over the urls and create a component and pass props.
}
});
My issue is that I can't find in the documentation how to pass the title and url parameter via the navigator to the specific screens.
Any Suggestions?
I can help you with one part, you can pass variables from Navigator like this
export default createMaterialTopTabNavigator({
ScreenOne: {
screen:props=> <ScreenOne {...props} screenProps={yourpropsr}/>
}
});
The documentation has example for StackNavigator but I hope this will work for TabNavigator too. Documentation link here
I'm doing something similar in my app, but I'm grabbing my array from an API and build my navigation upon that. For each item in my array, I build the same screen setup in a tab navigation and have them all available from a drawer navigator.
You could do something like this:
let NavigatorConfig = {};
urls.forEach(item => {
NavigatorConfig = {
...NavigatorConfig,
[item.title]: {
screen: props => <MyComponent {...props} url={item.url} />
}
};
});
export default createMaterialTopTabNavigator(NavigatorConfig);
I am on React native 0.29 for android. I used navigator in my app so that user can navigate from one view to another. I want to know is there any way I can show a loading symbol when navigator is navigating from one view to another.
I assume that the reason you're navigation is delayed is because you're fetching data asynchronously to prepare the next view. This answer isn't going to be very helpful if you've just got a performance concern.
Anyway, I've followed this basic pattern, basically I set the loader to true, then after I have the data, I set the loader to false and pass the data along to the view as a prop.
_handleLogin() {
this.setState({
isLoading: true,
},
() =>
Api.getUser( username, password )
.then( user => this._handleResponse( user ))
);
}
_handleResponse( user ){
this.setState({
isLoading: false,
})
this.props.navigator.push({
title: 'Home',
component: Home,
passProps: {
user: user,
}
});
}