React Native Navigation: Check if drawer is opened or not - reactjs

i have a component that is outside the Drawer tag but it's inside a NavigationContainer.
So i used useRef from react to get navigate method .
So i use this example: Navigating without navigation prop
But now, i can't get the state of the drawer (is it opened or closed).
Here's my App component:
import 'react-native-gesture-handler';
import React from 'react';
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { Provider } from "react-redux";
import GetInformationByLocation from "./reducers/GetInformationByLocation";
import Wrapper from './components/Wrapper';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import GeoDisplay from "./components/GeoDisplay";
import { Text } from "react-native";
import { navigationRef } from "./helpers/Navigator";
const store = createStore(GetInformationByLocation, applyMiddleware(thunk));
/*
* TODO:
* 1. Wrap everything with parent component
* 2. Search bar
* 3. Save searched cities.
* 4. Check if the city is undefined and suggest nearest city.
* 5. Animated background
* 6. Fancy and animated font
* 7. Setup menu преди показване на приложението
*/
const Drawer = createDrawerNavigator();
const App = () => {
return (
<Provider store={store}>
<NavigationContainer ref={navigationRef}>
<Wrapper />
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={GeoDisplay} />
</Drawer.Navigator>
</NavigationContainer>
</Provider >
);
}
export default App;
and my Wrapper.js Component:
import React, { useEffect, useState } from 'react';
import { StyleSheet, View, StatusBar } from 'react-native';
import { SearchBar, Header } from 'react-native-elements';
import { MainUI } from '../styling/UI';
import * as Navigator from "../helpers/Navigator";
import { DrawerActions } from "#react-navigation/native";
const Wrapper = (props) => {
const [search, setSearch] = useState(true);
const openDrawer = () => {
Navigator.navigationRef.current.dispatch(DrawerActions.openDrawer())
setSearch(false);
}
useEffect(() => {
}, []);
return (
<>
<StatusBar backgroundColor={"#011E25"} />
<Header
leftComponent={{ icon: 'menu', color: '#fff', onPress: () => { openDrawer() } }}
centerComponent={{ text: 'COVID Bulgaria', style: { color: '#fff' } }}
rightComponent={{ icon: 'home', color: '#fff' }}
backgroundColor={'#011E25'}
/>
{search &&
<View>
<SearchBar placeholder="Търси град" containerStyle={MainUI.searchContainer} />
</View>
}
</>
)
}
export default Wrapper;
I dispatch openDrawer() action with navigationRef
Navigator.navigationRef.current.dispatch(DrawerActions.openDrawer())
but can't get status of the drawer.
I've tried many ways but not work.
Thanks in advance.

You can check if drawer is open by getting the navigation state:
const state = navigationRef.current.getRootState();
const isDrawerOpen = state.history.some((it) => it.type === 'drawer');
The above code assumes that drawer is at root. If it's nested, you'll need to traverse the state to find the state object with type: 'drawer'.
It's not clear why you need to check it from the question. Normally you shouldn't need to check it. If you dispatch DrawerActions.openDrawer() if drawer is already open, nothing will happen. So the check is unnecessary. If you want to close the drawer if it was open, you can dispatch DrawerActions.toggleDrawer() instead.

You can create a helper class like:
class DrawerHandler() {
openDrawer() {
this.drawerOpened = true;
}
closeDrawer() {
this.drawerOpened = false;
}
getDrawerStatus() {
return this.drawerOpened;
}
}
export default new DrawerHandler();
Use open and close functions on drawer opening and closing and get function to get status of the drawer

Related

React Native : Rendered more hooks than during the previous render

I am getting this error after implementing the gethomeid useState and cant understand I tried different things but nothing worked
import React, {useEffect, useState} from 'react';
import {
StyleSheet,
View,
Image,
Text,
TouchableOpacity,
Button,
} from 'react-native';
import {windowWidth, windowHeight} from '../utils/Dimentions';
//components
import EmptyContainer from '../components/EmptyContainer';
import Header from '../components/Header';
import TopTabs from '../components/Tabs';
//redux
import {getHomeData} from '../action/homedata';
import {connect} from 'react-redux';
import propTypes from 'prop-types';
// to render empty container
const Home = ({getHomeData, homeState, userDetails}) => {
const [gethomeid, setGethomeid] = useState(null);
if (userDetails) {
useEffect(() => {
getHomeData('123456');
}, []);
}
if (homeState.data != null && userDetails && gethomeid != null) {
console.log(homeState.data);
return (
<View style={{flex: 1}}>
<Header username={userDetails.name.split(' ')[0]} />
<TopTabs roomdata={homeState.data.roomMapper} />
</View>
);
} else {
return (
<View>
<EmptyContainer />
</View>
);
}
};
const mapStateToProps = state => ({
homeState: state.data,
userDetails: state.auth.user,
});
const mapDispatchToProps = {
getHomeData,
};
Home.propTypes = {
getHomeData: propTypes.func.isRequired,
homeState: propTypes.object.isRequired,
userDetails: propTypes.object,
};
export default connect(mapStateToProps, mapDispatchToProps)(Home);
I am trying to load 2 buttons that will pass the data on clicked to the gethomeid but this error i am not able to solve
THE SNAPSHOT OF THE ERROR:-
You are conditionally calling the useEffect hook. This breaks the rules of hooks. You can likely move the conditional into the hook callback.
useEffect(() => {
if (userDetails) {
getHomeData('123456');
}
}, []);
You should probably also add any missing dependencies the linter may complain about, like userDetails and getHomeData.
useEffect(() => {
if (userDetails) {
getHomeData('123456');
}
}, [getHomeData, userDetails]);

After enclosing App inside Context, screen is not rendering anything

i am trying to build a react native blog app with context to transfer data to any child
here is my App.js
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import IndexScreen from './src/screens/IndexScreen';
import { BlogProvider } from './src/context/BlogContext';
const Stack = createStackNavigator();
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName='Index'>
<Stack.Screen name="Index" component={IndexScreen} options={{title: 'Blogs'}}/>
</Stack.Navigator>
</NavigationContainer>
);
}
//export default App;
export default () => {
return (
<BlogProvider>
<App/>
</BlogProvider>
)
}
here is my BlogContext.js
import React from 'react'
const BlogContext = React.createContext();
//const BlogContext = NavigationContext;
export const BlogProvider = ({ childern }) => {
return (<BlogContext.Provider>
{childern}
</BlogContext.Provider>
)
}
export default BlogContext;
Index.js
import React from 'react'
import { View, Text, StyleSheet } from 'react-native'
const IndexScreen = () => {
return (
<View>
<Text> index screen</Text>
</View>
)
}
const styles = StyleSheet.create({});
export default IndexScreen;
it is rendering on my ios simulator blank, if i don't enclose App within BlogProvider it renders successfully. i am trying to learn react native with udemy, not sure about how context work, any help would be appreciated, Thanks
You misspelled children, so nothing is actually getting rendered by BlogProvider.

My react hooks fail when used inside my react component that is deeply nesed into my react application

When I use useHistory hook here ...
import React from 'react';
import {View,Image,StyleSheet, TouchableOpacity} from 'react-native';
import theme from '../theme';
import Text from './Text'
import {useQuery} from '#apollo/react-hooks'
import {GET_REPOSITORY} from '../graphql/queries'
import {useHistory} from 'react-router-native'
const RepositoryItem = (props) => {
let history = useHistory()
let item = props.item
const styles = StyleSheet.create({
...
});
const reduceToK = (num) => {
if (num > 999) {
const thousandsNum = Math.round(num / 1000);
const remainerNum = Math.round((num % 1000) / 100);
return `${thousandsNum}.${remainerNum}k`;
} else return num;
};
return (
<View style={styles.rootContainer}>
{...}
</View>
);
};
export default RepositoryItem;
The application breaks and returns the following error ...
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM)2. You might be breaking the Rules of Hooks3. You might have more than one copy of React in the same app
This component (RepositoryItem) is being used inside another component (RepositoryList) like so ...
import React from 'react';
import { FlatList, View, StyleSheet, Text } from 'react-native';
import RepositoryItem from './RepositoryItem';
// ...
const styles = StyleSheet.create({
...
});
const RepositoryList = () => {
let history = useHistory()
const repositories = useQuery(GET_REPOSITORIES, {fetchPolicy: 'cache-and-network'});
if (!repositories.loading) {
const ItemSeparator = () => <View style={styles.separator} />;
// Get the nodes from the edges array
const repositoryNodes = repositories.data.repositories && !repositories.loading
? repositories.data.repositories.edges.map(edge => edge.node)
: [];
return (
<FlatList
data={repositoryNodes}
ItemSeparatorComponent={ItemSeparator}
renderItem={RepositoryItem}
keyExtractor={repository => repository.fullName}
/>
);
} else {
return (<View><Text>Loading...</Text></View>);
}
};
export default RepositoryList;
That component is being used in the App component.
My theory is that in react native's FlatList renderItem prop one cannot use hooks.
Any idea what the issue might be here?
You may want to do it this way because renderItem accepts a function.
<FlatList
data={repositoryNodes}
ItemSeparatorComponent={ItemSeparator}
renderItem={({item}) => <RepositoryItem item={item} />}
keyExtractor={repository => repository.fullName}
/>
change
import {useHistory} from 'react-router-native'
t0
import {useHistory} from 'react-router-dom'
based on react-router-native documentation

React Native View and Flex: 1 not working as expected

I learning React Native and I'm doing a simple View and setting the style to a container style, but nothing happens when I run the code. The View is now filling with the color read from the code. Its very starter code, just not seeing where its going wrong? When I run this, nothing in the view changes, it just white? I was expecting to see a screen of red?
import React, { useState } from 'react';
import {View, Text, StyleSheet, ScrollView} from 'react-native';
import { Input } from 'react-native-elements';
import SLSHeader from '../app-components/slsheader';
export default function Home (props) {
return (
<View styles={styles.container}>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'red'
}
});
The only place Im using it thus far is in a Navigator file... Its a switch Navigator with a Drawer Navigator...
import React from 'react';
import { createAppContainer, createSwitchNavigator} from 'react-navigation';
import { createDrawerNavigator } from 'react-navigation-drawer';
//import CustomDrawer from './CustomDrawer';
//Import Screens
import LoginScreen from '../screens/Login';
import HomeScreen from '../screens/Home';
//Drawer Screens
const DrawerScreens = {
Home: {
screen: HomeScreen,
navigationOptions:{
headerShown: false
}
}
}
const DrawerNavigator = createDrawerNavigator(DrawerScreens, {
defaultNavigationOptions: {
headerStyle: {
height: 60
}
},
//contentComponent: CustomDrawer
});
//Pre Login Screens
const PreLoginScreens = {
Login: {
screen: LoginScreen,
navigationOptions:{
headerShown: false
}
},
PostLogin: {
screen: DrawerNavigator
}
}
const PreloginNavigator = createSwitchNavigator(PreLoginScreens,{
defaultNavigationOptions: {}
});
export default createAppContainer(PreloginNavigator);
Yes, in the App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import SLSNavigator from './Navigation/SLSNavigator';
export default function App() {
return (
<SLSNavigator />
);
}

UI Kitten: can't find variable index (BottomNavigation)

Actually i'm trying to use BottomNavigation from UI Kitty but when i'm trying to swap from one navigation tab to another the app crash with the following error:
can't find variable index
Here is the code from BottomNavigation where i use index
import React from 'react';
import { BottomNavigation, BottomNavigationTab } from 'react-native-ui-kitten';
import { createAppContainer } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import Dashboard from '../navigation/Dashboard';
import Settings from '../navigation/Settings';
export const BottomNavigationShowcase = (props) => {
const onTabSelect = (selectedIndex) => {
const { [index] : selectedRoute } = props.navigation.state.routes; // INDEX IS USED HERE
props.navigation.navigate(selectedRoute.routeName);
};
return (
<BottomNavigation
selectedIndex={props.navigation.state.index}
onSelect={onTabSelect}>
<BottomNavigationTab title='Dashboard' />
<BottomNavigationTab title='Settings' />
</BottomNavigation>
);
}
export const BottomTabNavigator = createBottomTabNavigator({
Dashboard: Dashboard,
Settings: Settings,
}, {
initialRouteName: 'Dashboard',
tabBarComponent: BottomNavigationShowcase,
});
export default createAppContainer(BottomTabNavigator)
And here is App.JS
import NavigationContainer from './components/BottomNavigation';
const App: () => React$Node = () => {
return (
<ApplicationProvider mapping={mapping} theme={lightTheme}>
<IconRegistry icons={EvaIconsPack} />
<Header/>
<NavigationContainer/>
</ApplicationProvider>
);
};
There seems to be a problem in const { [index] : selectedRoute } = props.navigation.state.routes; // INDEX IS USED HERE
which is not the right way to read an object.
It seems like you want to read the routes from the props. Why not do something like
const routes = props.navigation.state.routes;
const selectedRoute = routes[selectedIndex];
props.navigation.navigate(selectedRoute.routeName);
This should fix the app from crashing due to not finding index

Resources