Why navigation.closeDrawer is not a function? - react-native

Dependencies version:
"dependencies": {
"react": "16.3.1",
"react-native": "~0.55.2",
"react-navigation": "^2.0.1",
}
I use react-navigation to navigate my screen, i create two screen and a drawer
Router.js:
import { createStackNavigator, createDrawerNavigator } from 'react-navigation';
import MainActivity from './components/MainActivity';
import ThisWeek from './components/ThisWeek';
import DrawerPanel from './components/DrawerPanel';
const Stack = createStackNavigator({
MainActivity: {
screen: MainActivity,
navigationOptions: {
title: 'Welcome',
headerStyle: {
backgroundColor: '#81A3A7',
elevation: null
}
}
},
ThisWeek: {
screen: ThisWeek
}
},
{
initialRouteName: 'MainActivity'
}
);
const Router = createDrawerNavigator({
FirstScreen: {
screen: Stack
}
},
{
contentComponent: DrawerPanel,
drawerWidth: 200
});
export default Router;
In my DrawerPanel.js i can click the two button navigate to the screen, but when i try to use this.props.navigation.closeDrawer(); that shows an error _this2.props.navigation.closeDrawer is not a function.
So i try to console.log(this.props);,i can see openDrawer and closeDrawer under navigation
Here is my DrawerPanel.js:
import React, { Component } from 'react';
import { ScrollView, FlatList, Text } from 'react-native';
import { View } from 'react-native-animatable';
import { List, Button } from 'react-native-elements';
class DrawerPanel extends Component {
render() {
console.log(this.props);
return (
<ScrollView style={{ backgroundColor: '#81A3A7' }}>
<Button
onPress={() => {
this.props.navigation.actions.closeDrawer();
this.props.navigation.navigate('MainActivity');
}}
backgroundColor={'#81A3A7'}
containerViewStyle={{ width: '100%', marginLeft: -61 }}
title='Main page'
/>
<Button
onPress={() => this.props.navigation.navigate('ThisWeek')}
backgroundColor={'#81A3A7'}
containerViewStyle={{ width: '100%', marginLeft: -46 }}
title='This weel'
/>
</ScrollView>
);
}
}
export default DrawerPanel;
I can't figure it out why i can use this.props.navigation.navigate(); to another screen not allow to use this.props.navigation.closeDrawer();
I try make a change to use this.props.navigation.actions.closeDrawer(); the error will show Cannot read property 'closeDrawer' of undefined.
What step i make it wrong ? Any help would be appreciated. Thanks in advance.

Try this
import { DrawerActions } from 'react-navigation';
this.props.navigation.dispatch(DrawerActions.closeDrawer());
this.props.navigation.dispatch(DrawerActions.openDrawer());

You are using both StackNavigator and DrawrNavigator so that the way to use them is different a little bit.
Keep in mind we have two version for react-navigation (v1 and v2) for now so that you should read the documentation carefully.
Please try using this:
Close drawer
this.props.navigation.navigate('DrawerClose'); // for version 1
this.props.navigation.openDrawer(); // for version 2
Open drawer:
this.props.navigation.navigate('DrawerOpen'); // for version 1
this.props.navigation.closeDrawer(); // for version 2
Be careful for reference any bugs fix for this libraries on the internet which you have to know which version is using in.
Note that the order of nesting - if the stack navigator is not inside of the drawer, it will not have the openDrawer function.
I guess it will work for you in this case.
Cheer!

In your DrawerPanel file. You did not use the constructor. Hence, your component's props did not know about the navigation props that the DrawerNavigator passed in. Try putting this before your render function in the component.
constructor(props){
super(props);
}
This way you will no longer need to use dispatch(), but instead use openDrawer() and closeDrawer().

Related

How to make a route in react native?

The routers Is not working, I tryed many forms but not worked, can someone help me?
the following error is: Device: (487:41) undefined is not an object (evaluating '_this2.props.navigation.navigate')
import { createDrawerNavigator, createAppContainer } from "react-navigation";
import Noturno from './containerNoturno.js';
import Linhas from './Linhas.js';
import LSaida from './LinhasSaida.js';
import Main from './containerDiurno.js';
import Ajuda from './Ajuda.js';
import Sobre from './sobre.js';
import Intro from './intro.js';
import GalopolisSantaCoronaNoturno from './Noturno/GalopolisSantaCorona.js';
const AppNavigator = createDrawerNavigator({
Menu: { screen: Main },
Noturno: { screen: Noturno },
Linhas: { screen: Linhas },
Linhas_Saida: { screen: LSaida },
Ajuda: { screen: Ajuda },
Sobre: { screen: Sobre },
Galopolis_Noturno: { screen: GalopolisSantaCoronaNoturno },
});
export default createAppContainer(AppNavigator);
here is the other code:
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Noturno')}
style={styles.fab}>
<Image
source={require('../assets/noite.png')}
style={{ width: 50, height: 50 }}
/>
</TouchableOpacity>
Please open the follow link and help me...
You are accessing the navigation prop in child component "Noturno.js" which is not part of StackNavigator
You can access the prop like this (Access the navigation prop from any component)
Update file "Noturno.js"
import { withNavigation } from 'react-navigation';
....
class App extends React.Component
....
export default withNavigation(App);

React-navigation: Increase height of the bottom tab navigation?

I created a simple tab navigation for a React Native app using react-navigation. It works fine, but I can't seem to adjust the height of it. It'll only go to a max of about 80, I need it to be about 150% of the current height, maybe double.
Does anyone know how to increase the height of the tab nav (preferably without creating about 6 more js files? ) I only have a limited period to fix it as I'd like.
Below is the nav code as-is
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { createBottomTabNavigator, createAppContainer } from "react-navigation";
import HomeScreen from './screens/HomeScreen';
import AboutScreen from './screens/AboutScreen';
import SettingsScreen from './screens/SettingsScreen';
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
const AppNavigator = createBottomTabNavigator({
Home: {
screen: HomeScreen
},
About: {
screen: AboutScreen
},
Settings: {
screen: SettingsScreen
}
}, {
initialRouteName: "Home"
});
const AppContainer = createAppContainer(AppNavigator);
Thanks
As said in the docs, you just need to add screenOptions={tabBarStyle:{height:100}}
For example:
bottomNavigatorConfigs = {
initialRouteName: "HomeScreen",
screenOptions: {
tabBarStyle: { height: 300 },
},
};
This is an example of the bottomNavigatorConfigs (tested) and working.
Where bottomNavigatorConfigs is used like this:
createBottomTabNavigator(bottomRoutesConfig, bottomNavigatorConfigs);
Source: https://reactnavigation.org/docs/bottom-tab-navigator/#options
Be careful with an iPhone's home indicator as you need to take account of the extra space at the bottom of the iPhone when setting absolute height.
import { useSafeAreaInsets } from 'react-native-safe-area-context';
...
export const Navigation = () => {
const insets = useSafeAreaInsets();
return (
<NavigationContainer>
<Tab.Navigator
tabBarOptions={{
style: {
height: 60 + insets.bottom,
...
},
tabStyle: {
height: 60,
...
},
...
}}>
...
tabBarOptions: {
style: {
height: '50%',
}
}
try that may be working.
With react navigation 6 you can just use:
tabBarStyle : {
height: 150,
...
}
screenOptions={
{
headerShown:false,
tabBarActiveTintColor:Colors.primary,
tabBarInactiveTintColor:Colors.primary2,
tabBarStyle: { height: 60 }
}
}

How to "lazy load" tab navigator screens now that lazy has been removed from react-navigation

The maintainers of react-navigation have removed 'lazy: true' from the library, causing all tabs to attempt to render at once (and fetches previously controlled by lazy now firing out of order).
In order to maintain similar functionality, how do you force a wait on a tab screen to not load or call fetch calls prior to being focused for the first time?
It seems they did remove it, but have decided to add it back in v 1.1.2
https://github.com/react-navigation/react-navigation/releases/tag/v1.1.2
Thus, you should be able to pass lazy={true} in your TabNavigatorConfig object, and then tabs will not be rendered before they are active. To further optimize memory usage, you can couple this with removeClippedSubviews to free memory from inactive tabs.
You can use LazyLoading from react-navigation-utils
React-navigation now suports withNavigationFocus wrapper.
You can use it to wrap the screen you want to prevent updating when it is not focused.
import React from 'react';
import { Text } from 'react-native';
import { withNavigationFocus } from 'react-navigation';
class LazyScreen extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return nextProps.isFocused;
}
render() {
return <Text>{this.props.isFocused ? 'Focused' : 'Not focused' </Text>;
}
}
export default withNavigationFocus(LazyScreen);
P.S. if you use Redux just do
export default connect(mapStateToProps, mapDispatchToProps)(withNavigationFocus(LazyScreen));
lazy={true}
optimizationsEnabled={true}
tabBarOptions={tabBarOptions}
the above code is important, try it
import { createMaterialTopTabNavigator } from "#react-navigation/material-top-tabs";
import { createStackNavigator } from "#react-navigation/stack";
const TabNavigator = createMaterialTopTabNavigator();
const Stack1 = createStackNavigator();
const Stack2 = createStackNavigator();
const ProductsScreen = (props) => {
//
return (
<TabNavigator.Navigator
lazy={true}
optimizationsEnabled={true}
tabBarOptions={tabBarOptions}
>
<TabNavigator.Screen name="HOME" component={StackScreen1} />
<TabNavigator.Screen name="SHOP" component={StackScreen2} />
</TabNavigator.Navigator>
);
};
const tabBarOptions = {
indicatorStyle: {
height: null,
top: 0,
backgroundColor: "#ccc",
borderBottomColor: "black",
borderBottomWidth: 3,
},
activeTintColor: "black",
style: {
backgroundColor: "red",
},
labelStyle: { fontSize: 13 },
};
How about this?
const MyTab = TabNavigator({
tab1:{screen:TabScreen1},
tab2:{screen:TabScreen2}
}
class MainScreen extends React.Component{
constructor(){
super();
this.state = {
loading:true
}
}
componentWillMount(){
//fetch login
//set loading:false when fetch is done
}
render(){
!this.state.loading && <MyTab/>
}
}
In the new versions of React Navigation the lazy prop is set to true by default.
See https://reactnavigation.org/docs/en/bottom-tab-navigator.html#lazy

Using Redux with React Native

I am working on a react-native app created using: create-react-native-app
As far as I can tell the most top level component is inside the App.js file and I have imported the Provider there and wrapped it around the Top Level Component but I am still getting the following errors for some reason:
ExceptionsManager.js:65 Invariant Violation: Could not find "store" in
either the context or props of "Connect(App)". Either wrap the root
component in a , or explicitly pass "store" as a prop to
"Connect(App)".
What am I doing wrong?
Here is my code:
import React from 'react';
import { StyleSheet, Text, View, FlatList, TextInput, StatusBar, Button,TouchableOpacity } from 'react-native';
import { TabNavigator, StackNavigator } from 'react-navigation';
import { Constants } from 'expo'
import { purple, white } from './utils/colors'
import { saveDeckTitle, getDecks, getDeck, addCardToDeck } from './utils/api'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import reducer from './reducers'
import { connect } from 'react-redux'
import Decks from './components/Decks'
import NewQuestionView from './components/NewQuestionView'
import NewDeck from './components/NewDeck'
const R = require('ramda')
const store = createStore(reducer)
const DecksETC = StackNavigator({
Decks: {
screen: Decks
},
NewDeck: {
screen: NewDeck
},
NewQuestionView: {
screen: NewQuestionView
}
})
const NewDeckETC = StackNavigator({
NewDeck: {
screen: NewDeck
},
Decks: {
screen: Decks
},
NewQuestionView: {
screen: NewQuestionView
}
})
const Tabs = TabNavigator({
DecksETC: {
screen: DecksETC
},
NewDeckETC: {
screen: NewDeckETC
}
});
class App extends React.Component {
render() {
console.log('R', R)
return (
<Provider store={store}>
<Tabs />
</Provider>
// <Tabs />
);
}
}
const styles = StyleSheet.create({
container: {
paddingTop: 23,
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
input: {
margin: 15,
height: 40,
borderColor: '#7a42f4',
borderWidth: 1
},
});
function mapStateToProps(state) {
console.log('mapStateToProps')
debugger
return {
'sample': 'sample'
}
}
export default connect(mapStateToProps)(App)
The problem is that App component does not know anything about the store because the Provider component is what brings the Redux store into its children components. The App component itself does not receive a reference to the store, so when you try to connect, the store is not found.
Well I see you have use connect function for the root component directly, which is a pattern I never see before. Let's try the normal way, which is that you will create a Root component and just use it inside Provider. Then you will pass child components into that Root component.
You will then separate each child component into a new file. In each file, you will use connect() to pass redux store into that component. That's the common pattern I see in many many projects. And this pattern will help you avoid confusing situation like above!
Well the function connect requires two functions mapStateToProps and mapDispatchToProps as arguments
i.e. export default connect(mapStateToProps,mapDispatchToProps)(App)
if you do not have a mapDispatchToProps then simply pass null.
i.e. export default connect(mapStateToProps,null)(App)

React-Navigation: Route should declare a screen... error

I am new to react-navigation and I followed the steps on the site, however I get an error saying Route 'Chat' should declare a screen... Below is my code for reference.
import React from 'react';
import {
AppRegistry,
Text,
View,
Button,
} from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>Hello, Chat App!</Text>
<Button
onPress={() => navigate('Chat')}
title="Chat with Lucy"
/>
</View>
);
}
}
AppRegistry.registerComponent('navigationApp', () => navigationApp);
This is where I believe the error is occurring
const navigationApp = StackNavigator({
Home: { screen: HomeScreen },
Chat: { screen: ChatScreen },
});
class ChatScreen extends React.Component {
static navigationOptions = {
title: 'Chat with Lucy',
};
render() {
return (
<View>
<Text>Chat with Lucy</Text>
</View>
);
}
}
I'm facing the same issue as yours too here.Well, according to my solution,
what i did is I put the line with:
const navigationApp = StackNavigator({
Home: { screen: HomeScreen },
Chat: { screen: ChatScreen },
});
on top part, just above the AppRegistry... line. It should be in the index.android.js file.
And don't forget to include this line at the top of this file too:
import { ChatScreen } from './App';
And according to the tutorial that you're following(i believe it's the same as what i'm following right here), you should have one other file named 'app.js'; which you're referencing in the import line.
contents of 'app.js':
import React from 'react';
import { View, Text } from 'react-native';
export class ChatScreen extends React.Component {
static navigationOptions = {
title: 'Chat with Lucy',
};
render() {
return (
<View>
<Text>Chat with Lucy</Text>
</View>
);
}
}
That's it. However, it depends on the machine and system you're using. I'm using a MacBook pro with a Mac OS Sierra 10.12.6
And the react-native is also a latest version, not sure if there are more recent versions(there are quite a number of updates from time to time).
Try to modify a line/commands , whichever suits to your versions, and read the examples/tutorials carefully. There could be some deprecated functions/unusable codes, etc., due to some updates/ different system environment.
Good Luck!
If you have an index.js for your component or directory, don't forget to add the export there too! (Not that I've ever done that....)
A good article about organizing a project is and the use of index.js: Organizing a React Native Project on Medium
Put navigationOptions into like
{screen: ScreenComponent, navigationOptions: ...your options }