React this.props.navigation.openDrawer() in child component? - react-native

I have an openDrawer method via React Navigation 2 working great in my View. However, when I create a child component and place my openDrawer button in it, I can no longer access this.props.navigation. How do I pass that down into the child component? I looked at state but that doesn't seem to be the correct way to address this? I am new to React/Native. Here is my button inside the main view and it works fine this way.
<View style={styles.menuBar}>
<TouchableOpacity style={styles.menuButton}
onPress={() => this.props.navigation.openDrawer()}>
<Text>☰</Text>
</TouchableOpacity>
// Other Stuff inside menuBar.
</View>
This menu button has a few other items as well and I am wanting to group together in a class component as a child that I can just import into various screens.
import { topMenuBar } from '../components/menuBar';
<topMenuBar />
However, the menu button no longer works now. I know it's because this.props is now referring to class topMenuBar and not the original class which is part of the nav structure. But I don't know the proper procedure for this step, whether it's using state or calling NavigationActions from react-navigation in the child method somehow.
Thanks for the help!

Every component opened using react-navigation has "this.props.navigation".
If you need it in child components you should pass to them as a prop:
export default class Home extends Component{
render(){
<View>
<OtherComponent navigation = {this.props.navigation}/>
</View>
}
}
Note: if you want a better help you should always provide code creating a fiddle and organize better your answers..

Related

Why useNavigation hook doesn't work in custom side bar?

If I create custom drawer:
<DrawerStack.Navigator
drawerContent={props => <SideMenu {...props} />}>
It requires to pass props in order to get navigation object inside it.
And if I have following:
<ClientsStack.Navigator>
<ClientsStack.Screen name="Clients" component={ClientsScreen} />
<ClientsStack.Screen
name="ClientDetails"
component={ClientDetailsScreen}
/>
</ClientsStack.Navigator>
And inside ClientsScreen I have FlatList which has:
renderItem={({ item }) => <ClientCard id={item.id} />}
inside ClientCard component which is not screen it's just dummy component
I can use useNavigation hook there.
Why it can be used there but not in custom drawer component?
You can't use useNavigation inside your drawerContent cause the hook is only available from your screens and their childs.
At the origin the only way to get navigation was to pass it from your screen to their childs. But since the useContext hook exist, the library provides a useNavigation to easily get the navigation in deep nested components. (and simplify the code a lot)
A drawer custom component is not a screen or wrapped into a screen. So there is just no reason to get the navigation from it with useNavigation. And I easily guess there is no usecase where we have deep nested components inside it cause it is usually just a menu.

React native partial modal

I am working on a react-native app using react navigation.
I want to add a partial modal that covers 30% of screen when pressing on one of the tabs in the bottom-tab, similar to the "+" tab in the YouTube app:
Youtube modal
I've tried to use react-native Modal component, but
I have problems with activating it from bottom tab
it covers whole screen
Any suggestions?
Thanks..
To answer your question 100% correct I'd need to know more details about your project but, I can try to explain how can be your logic to do this withou any libs.
You can create another component called "Start" where you're gonna put your Modal with absolute position above your navigator.
You can create a Modal that will be above your navigator:
export const Start(){
return(
<View style={{flex:1}}>
<Modal>
<View/>
</Modal>
<NavigatorComponent/>
</View>
)
}
This is going to work because when you put a component with absolute position above the other, this component stay in front of the below component. In your case, will stay in front of everything including the TabBar.
To the modal has just 30% of the height you just need to put in its styles the attribute height: '30%'.
In the initial component of your App (usually the index.js file), you just return the new Start component.
I hope you like my answer. Please, if you have more questions you can ask. Waiting for your feedback :).

Change SVG component on press with React Native

Background
Pretty simple question: I want to create a "like" button in RN. To do this I have to separate components which are SVG files. One is just the outline of a heart, the other one is filled.
The screen in which I'm trying to build this button is a Function component so I should use hooks. I know about state but don't know how to properly use it.
What I need
A Touchable Opacity component which holds an onPress method which changes the image component when pressed.
Thanks a lot in advance!
import React ,{useState} from 'react';
import {TouchableOpacity } from "react-native";
export default function Like() {
const [isLiked,setIsLiked]=useState(false) ;
const handleLikePress=()=>{
setIsLiked(!isLiked)
}
return (
<TouchableOpacity onPress={handleLikePress}>
{isLiked? <FilledHeartSVG/>: <OutlineHeartSVG/> }
</TouchableOpacity>
)
}
by default, we are showing an outline of a heart SVG
when press event trigger we are changing isLiked state value
if isLiked is true then show filled heart SVG
if isLiked is false then show outline of a heart SVG
FilledHeartSVG and OutlineHeartSVG is just example use your SVG there
You can do something like below, here i have made a toggle for the text but you can change it to your image component, also the callback prop can be used if you want to use that outside the LikeButton
const LikeButton = ({callback}) => {
const [liked, setLiked] = React.useState(false);
return (
<TouchableOpacity onPress={()=>{
setLiked(!liked);
if(callback)
{
callback();
}
}}>
<Text>{liked?"Liked":"Like"}</Text>
</TouchableOpacity>
);
};
You can tryout this snack which uses icons
https://snack.expo.io/#guruparan/likebutton

Splash screen with PersistGate

I have below code base
Navigator.js
export default createAppContainer(createSwitchNavigator(
{
// screendesign: screendesign,
SplashScreen: SplashScreen,
App: drNav,
AuthStack: AuthStack
},
{
initialRouteName: 'SplashScreen',
}
));
import SplashScreen from './screens/SplashScreen'
<Provider store={store}>
<PersistGate loading={<SplashScreen/>} persistor={persistor}>
<View style={styles.container}>
<Navigator />
</View>
</PersistGate>
</Provider>
splashScreen.js
componentDidMount() {
if (this.state.isAuthenticated) {
this.props.navigation.navigate("App");
}
else {
this.props.navigation.navigate("AuthStack");
}
}
I am getting below error
Before implementing redux, I have used this page as entry screen for
my app, showing as splash screen and behind checking if user is
authenticated or not, if it is authenticated redirecting to login page
else dashboard. It was working fine, but now I have used redux, then
the scenario is working similarly only diff this screen is not visible
since redux persis load data from storage
Please help I am new in react native unable to understand this error
Thanks
The navigation prop is available to all components defined inside the navigator.
The SplashScreen component is not part of your Navigator so it doesn't have access to the navigation prop.
But I don't think you need it there.
Your SplashScreen component is a dump component that will be shown to the user for as long as the PersistGate needs to load the stored data to your redux store.
So when the loading of the data is completed you will see the rest of the components as they are defined inside the PersistGate. So I don't see why you would need to use the navigation from this loading component.
In case you do really need to access the navigation prop from the SplashScreen you can follow this guide: https://reactnavigation.org/docs/en/connecting-navigation-prop.html
Looks like your code unable to find navigation in SplashScreen component.
1) Try to console that in SplashScreen component's render method.
2) Also check for redux configuration, there may be case that issue is with your redux configuration because of that your component unable to access navigation props.

Pass touch event to view's parent in react native.

I have a <view> touching which will open a collapsible view. I have used react-native-collapse-view for it (https://www.npmjs.com/package/react-native-collapse-view) I have <text> on top of <view> which is covering it full. I am setting some conditions in onPress event of the <text> element.
Now what I want is if I touch the <text> (obviously I cannot touch view as text is covering it fully), along with onPress event of the <text> the underlaying <view> should also be touched so that it opens the collapsible view.
In short I want to pass the touch event to the parent view in order to complete all work in one touch. I searched and found some content related to onStartShouldSetResponder and pointerEvents but I couldn't get the complete grip as I am a newbie to react native.
in short you need pass function to children for handling events
import React from "react";
class ChildComponent extends React.PureComponent {
render() {
const {handleChildPress} = this.props;
return <Text onPress={handleChildPress}/>;
}
}
class ContainerComponent extends React.PureComponent {
// you need pass this func to children
// =()=> means bind it
handleChildPress=()=>{
console.log('child pressed')
}
render() {
return <ChildComponent handleChildPress={this.handleChildPress}/>;
}
}
export default ContainerComponent