How to use useLayoutEffect in Class component - react-native

The documentation here https://reactnavigation.org/docs/header-buttons says I need to use useLayoutEffect to trigger a function from another file but I am using a class component and have no plan to switch to that other type.
How do I re write this file so I can get access to navigation.getParam because now it's undefined
export default class Dashboard extends React.Component {
constructor() {
super();
this.state = {
};
}
onLogout = () => {
alert.alert('Alert', 'Testing...')
}
componentDidUpdate(){
this.props.navigation.setParams({ onLogout: this.onLogout});
}
componentDidMount() {
this.props.navigation.setParams({ onLogout: this.onLogout});
}
render() {
return (
<View style={styles.container} />
);
}
}
Navigation code
<BottomTab.Screen
name="Dashboard"
component={Dashboard}
options={({ route, navigation }) => ({
// title: "Dashboard",
tabBarIcon: () => <Icon name="printer" size={20} color="black" />,
headerLeft: () => (
<Icon style={{ marginLeft: 14 }} name="user" size={20} color="black" />
),
headerRight: (
<Button
onPress={navigation.getParam('onLogout')}
/>
)
})}
/>

Related

React navigation 5.0 header button

I trying to add right navigation header button directly on from Component, and implementation steps have been changed navigation 5.0 version, there is one method that provide add button with method
function HomeScreen({ navigation }) {
const [count, setCount] = React.useState(0);
navigation.setOptions({
headerRight: () => (
<Button onPress={() => setCount(c => c + 1)} title="Update count" />
),
});
return <Text>Count: {count}</Text>;
}
but need to implement on it
export default class HomeScreen extends Component {
constructor() {
super()
}
render() {
return ()
}
}
You can do this in your component constructor
this.props.navigation.setOptions({
headerRight: () => <Button />
});
Try this
<Stack.Screen
code..//
options={{
code...//
headerRight: () => (
<Button
onPress={() => alert('This is a button!')}
title="Info"
color="#fff"
/>
),
}}
/>

having problem with react-native navigation | undefined is not an object (evaluating '_this.props.navigation')

hi i'm working on a new react-native app, but i had some issues with the navigation from a component to a screen.
this is the link for the code on snack: https://snack.expo.io/#mimonoux/my-app-navigation-test
i have already tried this
<ButtonCarte onPress={() => this.props.navigation.navigate('Carte') } />.
but it didn't work. please if anyone could help me with this please check the snack link and take a deep look at the easy code i made for my real problem
I saw your problem now. With react-navigation,
navigation props exists in a component when : either the component is configured in your route configuration object that you defined in App.js, either you use the withNavigation HOC ( https://reactnavigation.org/docs/en/with-navigation.html ).
Now in the Medicine_listDetail component this.props.navigation does not exist since Medicine_listDetail does not appear in your route and also the props object should not be read by this.props in a functional component. You can do one of this two way :
const Medicine_listDetail = ({medicine, navigation}) => {
// i'm passing navigation props comme from parent component that have
// navigation object
// ...
}
// OR you can do
const Medicine_listDetail = (props) => {
const { medicine, navigation } = props;
// i'm passing navigation props comme from parent component that have
// navigation object
// ...
}
Hence the following is an attempt at a solution that work for me.
Medicine_listDetail component : i'm passing navigation props come from
parent component that have navigation object
...
const Medicine_listDetail = ({medicine, navigation}) => {
const {title, coordinate} = medicine;
const {
headerContentStyle,
headerTextStyle,
cityTextStyle,
addTextStyle,
infoContainerStyle,
buttonsContainerStyle,
specialityTextStyle,
buttonStyle,
textStyle
} = styles
return (
<View>
<View style={headerContentStyle}>
<Text style={headerTextStyle}>{title}</Text>
</View>
<View style={buttonsContainerStyle}>
<ButtonCarte onPress={() => navigation.navigate('Carte') }>
</ButtonCarte>
</View>
</View>
);
};
...
ButtonCarte component
const ButtonCarte = ({onPress, children}) => {
const {buttonStyle, textStyle} = styles;
return (
<TouchableOpacity onPress={() => onPress()} style={buttonStyle}>
<Ionicons name={'ios-pin'} size={20} color="white" />
<Text style={textStyle}>
Voir La Carte
</Text>
</TouchableOpacity>
);
};
Medicin component : in all_medicine() function, i'm passing navigation object in props of Medicine_listDetail component. So this is the trick.
export default class Medicin extends React.Component {
constructor(props) {
super(props);
this.state = {
list_allMedicine: data_allMedicine,
selectedIndex: 0,
};
this.updateIndex = this.updateIndex.bind(this);
}
updateIndex(selectedIndex) {
this.setState({ selectedIndex });
}
all_medicine() {
const { navigation } = this.props;
return this.state.list_allMedicine.map(medicine => (
<Medicine_listDetail key={medicine.title} medicine={medicine} navigation={navigation} />
));
}
render() {
const buttons = ['Tout', '...', '...', '...'];
const { selectedIndex } = this.state;
return (
<View style={{ flex: 1}}>
<View
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ButtonGroup
onPress={this.updateIndex}
selectedIndex={selectedIndex}
buttons={buttons}
containerStyle={{ borderRadius:8 }}
/>
</View>
<Divider
style={{
backgroundColor: 'lightgrey',
marginHorizontal: 5,
height: 2,
}}
/>
<View style={{ flex: 5 }}>
{this.state.selectedIndex == 0 ? (
<ScrollView>{this.all_medicine()}</ScrollView>
) : (
<Text>test</Text>
)}
</View>
</View>
);
}
}
At least in App.js, i change the name of carte tab from Cart to Carte because of your RootStack stack.
export default createAppContainer(
createBottomTabNavigator(
{
Home: {
screen: Home,
navigationOptions: {
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor }) => (
<Ionicons name={'ios-home'} size={25} color={tintColor} />
),
},
},
Medicin: {
screen: Medicin,
navigationOptions: {
tabBarLabel: 'Medicin',
tabBarIcon: ({ tintColor }) => (
<Image
source={require('./assets/images/Dashboard/drawable-xhdpi/doctor_heart.png')}
style={{ width: 25, height: 20, tintColor: tintColor }}
/>
),
},
},
Carte: {
screen: Carte,
navigationOptions: {
tabBarLabel: 'Carte',
tabBarIcon: ({ tintColor }) => (
<Ionicons name={'ios-map'} size={25} color={tintColor} />
),
},
},
},
{
tabBarOptions: {
activeTintColor: 'black',
inactiveTintColor: 'gray',
},
}
)
);
I test this and it work for me.
try adding this:
import { NavigationEvents, NavigationActions } from 'react-navigation';
Here is a screenshot of what's available in props in reference to the comments below:
Here is a screenshot of what I mentioned in the comments. You can see where I added a console.log. It shows in the console that although navigation is in this.props, actions within navigation is empty. I think that is the source of the problem. If you put more console.logs like the one I've done you will see where in the project it loses that information.

How to change drawer header value from another component?

I'm new on react native. I'm using createDrawerNavigator for drawer list in this list i used a component to render a header with logged in user name. But i want to change that name from another component( profile screen). I'm unable to find solution.
Here is my drawer navigator code :
const AppDrawerNavigator = createDrawerNavigator({
Home: {
screen: Home,
navigationOptions: {
drawerLabel: 'Home',
drawerIcon: () => (
<Icon name="home" size={20} color="#0f1f7b" />
)
},
},
Profile: {
screen: Profile,
navigationOptions: {
drawerLabel: 'Profile',
drawerIcon: () => (
<Icon name="user" size={20} color="#0f1f7b" />
),
},
},
Logout: {
screen: Logout,
navigationOptions: {
drawerLabel: 'Logout',
drawerIcon: () => (
<Icon name="sign-out" size={20} color="#0f1f7b" />
)
},
}
},
{
drawerBackgroundColor: "#fff",
contentOptions: {
activeTintColor: '#000',
inactiveTintColor: '#000',
activeBackgroundColor: '#bfc7f3',
itemStyle: {
fontSize: 12,
},
},
contentComponent: (props) => (
<View>
<ScrollView>
<DrawerUserDetail />
<DrawerItems
{...props}
getLabel = {(scene) => (
<View style={{width:width/1.9}}>
<Text style={{color:'#000',fontSize:18,fontWeight:'500',paddingBottom:10,paddingTop:10}}>{props.getLabel(scene)}</Text>
</View>
)}
/>
</ScrollView>
</View>
)
});
Here is drawer user detail code :
constructor(props){
super()
this.state={
name:'',
}
}
render() {
return (
<View style={styles.profileBg}>
<Text style={{fontSize:20,color:'#fff',fontWeight:'600',left:20}}>Hello! {this.state.name}</Text>
</View>
);
}
I want change name state from profile component whenever user update name it will reflect on drawer screen.
You can create a separate component and use this component in your DrawerNavigator.
<DrawerUserDetail navigation={props.navigation} />
And here is component :
export default class DrawerUserDetail extends Component<Props> {
componentDidMount() {
//You can call your API here.
}
<View style={styles.profileBg}>
<View style={styles.profileHeader}>
<Text style={styles.name}>{this.state.name}{' '}</Text>
<Text onPress={()=> this.props.navigation.navigate('ProfileUpdate')}
style={styles.changePassword}>Manage Account</Text>
</View>
</View>
}

react Navigation 3.x open drawer from header button?

I want to create a header on top with title for each screen and button on the right to open the drawer in react navigation 3.x
In the code below the header does not show.
//Updated with Current code
import React, { Component } from 'react';
import { Button } from 'react-native';
import {
createStackNavigator,
createDrawerNavigator,
createAppContainer
} from 'react-navigation';
import MyHomeScreen from './components/HomeScreen';
import MyNotificationsScreen from './components/ProfileScreen';
const MyDrawerNavigator = createDrawerNavigator(
{
Home: {
screen: MyHomeScreen
},
Notifications: {
screen: MyNotificationsScreen
}
},
{
initialRouteName: 'Home',
navigationOptions: navigationOptionsHeader
}
);
const navigationOptionsHeader = ({ navigation }) => {
return {
headerTitle: 'MY Home',
headerRight: (
<Button
onPress={() => navigation.toggleDrawer()}
title="Info"
color="#222"
/>
)
};
};
const AppContainer = createAppContainer(MyDrawerNavigator);
class App extends Component {
render() {
return <AppContainer />;
}
}
export default App;
Use this inside your screen class
static navigationOptions = ({ navigation }) => {
return {
title: 'Home',
headerLeft: (
< Icon name="menu" size={30} style={{marginStart:10}} backgroundColor="#000000" onPress={() => navigation.openDrawer()} > < /Icon>
),
};
};
try this
const MyDrawerNavigator = createDrawerNavigator(
{
Home: {
screen: MyHomeScreen
},
Notifications: {
screen: MyNotificationsScreen
}
},
{
initialRouteName: 'Home'
navigationOptions: navigationOptionsHeader,
}
);
const navigationOptionsHeader=({navigation})=>{
return {
headerRight: (
<Button
onPress={() => navigation.toggleDrawer();
}
title="Info"
color="#222"
/>
)
};
}
you can also add other stuffs in header like this
const navigationOptionsHeader=({navigation})=>{
return {
headerRight: (
<Button
onPress={() => navigation.toggleDrawer();
}
title="Info"
color="#222"
/>
)
headerLeft : <headerLeft/>,
title: //Header Title
headerStyle: { backgroundColor: '#161616', height:48, },
headerTitleStyle:{ color:'#cd9bf0', fontWeight: '400', alignSe
};
}
The navigationoptions had been renamed as defaultNavigationOptions in v3.
Please refer the documentation from https://reactnavigation.org/docs/en/headers.html
For React Navigation 5
Use the prop options as a function:
<Stack.Screen
name="screen name"
component={ScreenComponent}
options={({ navigation }) => ({
headerRight: (props) => {
return <Button onPress={() => navigation.toggleDrawer() }} />
}
})}
/>
https://reactnavigation.org/docs/upgrading-from-4.x/#configuring-the-navigator
For react navigation 5.x
<Stack.Screen
name="Home"
component={HomeScreen}
options={{
headerLeft: () => (
<View>
<Icon
onPress={() => navigation.toggleDrawer()}
name="menu"
/>
</View>
),
}}
/>

Cant navigate to next screen

I am trying to navigates screens with a stack navigator. The Idea is, my app will navigate from my list of chats, too the chat screen. However when I try to navigate to the next screen, I receive an error saying "undefined is not an object" on this.props.navigation. Here is what my code looks like:
MainTabNavigator (Contains my stack navigator)
const ChatListStack = createStackNavigator({
ChatList:ChatListScreen,
ChatView:ChatScreen,
});
ChatListStack.navigationOptions = {
tabBarLabel: 'ChatList',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={Platform.OS === 'ios' ? `ios-options${focused ? '' : '-outline'}` :
'md-options'}
/>
),
};
ChatListScreen (Where the navigation starts from)
export default class ChatListScreen extends Component {
constructor(props) {
super(props);
}
static navigationOptions = {
title: "Chats"
};
renderRow({ item }) {
return (
<TouchableHighlight
onPress={() => this.props.navigation.navigate("ChatView")}
>
<ListItem
roundAvatar
title={item.name}
subtitle={item.subtitle}
avatar={{ uri: item.avatar_url }}
/>
</TouchableHighlight>
);
}
goToChat() {}
render() {
return (
<View style={styles.mainContainer}>
<SearchBar
lightTheme
icon={{ type: "font-awesome", name: "search" }}
placeholder="Type Here..."
/>
<List style={styles.listContainerStyle}>
<FlatList
data={users}
renderItem={this.renderRow}
keyExtractor={item => item.name}
/>
</List>
</View>
);
}
}
Chat(This is the target Chat screen)
export default class ChatScreen extends Component {
constructor() {
super();
this.state = {
messages: []
};
}
componentWillMount() {
this.setState({
messages: [
{
_id: 1,
text: "Hello test",
createdAt: new Date(),
user: {
_id: 2,
name: "dude"
}
}
]
});
}
render() {
return (
<GiftedChat
messages={this.state.messages}
onSend={message => this.onSend(message)}
user={{
_id: 1
}}
/>
);
}
}
to solve this problem you must make a function to handle navigation then bind it in the contractor then send it in your Touchableopacity