Problem with my navigator in a class component - react-native

everyone,
I'm want to create a button which redirects to another view but it doesn't work. All my views are defined in homeStack.js:
const screens= {
LoginPage: {
screen: Login,
navigationOptions: {
headerShown: false
},
},
RegisterPage: {
screen: Register,
navigationOptions: {
headerShown: false
},
},
DetailsPage: {
screen: Details,
navigationOptions: {
headerShown: false
},
},
}
const HomeStack = createStackNavigator(screens);
export default createAppContainer(HomeStack);
Now I have a login class component containing different functions including:
renderLoginform(){
return (
<View style={{ flex: 1, backgroundColor: '#FC8686', justifyContent: 'center' }}>
<View style={{flex: 6, backgroundColor: 'white', borderBottomLeftRadius: 30, borderBottomRightRadius: 30, }}>
<SafeAreaView style={{alignItems: 'center', flex: 1, alignItems: 'center'}}>
<Text style={{fontSize: 40, flex: 1}}>Sign In</Text>
<View style={style.formContainerStyle}>
<View style={style.fieldStyle}>
<TextInput
placeholder="username"
autoCorrect={false}
autoCapitalize="none"
onChangeText={this.onUsernameChange.bind(this)}
style={style.textInputStyle}
textAlign={'center'}
/>
</View>
<View style={style.fieldStyle}>
<TextInput
secureTextEntry
autoCapitalize="none"
autoCorrect={false}
placeholder="password"
onChangeText={this.onPasswordChange.bind(this)}
style={style.textInputStyle}
textAlign={'center'}
/>
</View>
</View>
<View style={style.buttonzone}>
<View style={style.buttonContainerStyle}>
{this.renderButton()}
</View>
<View style={style.buttonContainerStyle}>
</View>
**<Button
title='Go to Register'
onPress={this.props.navigation.navigate('RegisterPage')}></Button>**
</View>
</SafeAreaView>
</View>
</View>
);
}
The last element of the code is a button whose click should link to my RegisterPage. But it won't work. What's wrong ?
This function is then called in the render return of the Login class.
Thanks for your help.

Try using this way
onPress={() => this.props.navigation.navigate('RegisterPage')}

Related

React Native: How can I put a pop-up Modal into flatlist

I've made a flatlist with a few data inside. I want to make a pop-up information for each item in the flatlist. So I tried putting Modal into the renderItem function but when it sets the modal state visible, it will show all of the information in my flatlist. I think it should be setting the modal visible state by id or something like that but I don't know how to do it. Any suggestion?
my renderItem:
function RenderItem({ item }) {
return (
<View>
<Modal
animationType='slide'
transparent={true}
visible={infoModal}>
<View style={styles.informationContainer}>
<View style={styles.informationBox}>
<Text>{item.file.displayName}</Text>
<Button title=' OK ' onPress={() => setInfoModal(false)} />
</View>
</View>
</Modal>
<TouchableOpacity style={styles.listBox} onPress={() => setInfoModal(true)}>
<View>
<Text numberOfLines={1} style={styles.listText}>{item.file.displayName}</Text>
<Text style={{ width: 200, color: 'rgba(0, 0, 0, 0.5)' }}>{item.certificateName}</Text>
</View>
<View style={{ flexDirection: 'row', justifyContent: 'center' }}>
<TouchableOpacity>
<Icon name='search' color='black' size={25} />
</TouchableOpacity>
<Text> </Text>
<TouchableOpacity onPress={() => handleDownload(item)}>
<Icon name='download' color='black' size={25} />
</TouchableOpacity>
<Text> </Text>
</View>
</TouchableOpacity>
</View>
)
}
Instead of setting a simple boolean value about whether the Modal should appear, you can set some sort of identifiable value that tells it what item to load (and otherwise leave it undefined).
Bare-bones example:
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
export default function App() {
const [modalInfo, setModalInfo] = React.useState(undefined);
const renderItem = ({ item }) => (
<TouchableOpacity onPress={() => setModalInfo(item.title)}><Text>{item.title}</Text></TouchableOpacity>
);
return (
<View style={styles.container}>
<Modal visible={modalInfo !== undefined}>
<View style={[{borderWidth: 1},styles.centeredView]}>
<Text>{modalInfo}</Text>
<TouchableOpacity onPress={() => setModalInfo(undefined)}><Text>Close</Text></TouchableOpacity>
</View>
</Modal>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</View>
);
}
const styles = StyleSheet.create({
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22
},
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
});

Align all icon to the right of page regardless of start point React Native

I want to be able to align all reply icons to the far right, where the red line is, regardless of where they start.
Edit: added more information to show how recursion is used in the component. Why I try to use some answers that work without recursion, I receive an undesired effect.
This is the code I have in place so far:
class Comment extends Component {
render() {
return(
<View>
<Header
rounded
style={{
backgroundColor: '#ffffff',
position: 'relative',
}}
>
<View style={{flexDirection: 'row', flexWrap: 'wrap', right: '43%', top: '50%'}}>
<Icon name='chevron-left' size={10} color='#006FFF' style={{top: '6%'}}/>
<NativeText
onPress={() => this.props.history.push('/')}
style ={{color: '#006FFF', fontSize: 12, fontFamily: 'Montserrat-Regular'}}
>
Back
</NativeText>
</View>
</Header>
<View
style={{paddingLeft: '2%', paddingTop: '2%'}}
>
<CommentList
options={this.props.location.state.comments}
currentUser={this.props.location.state.currentUser}
history={this.props.history}
reportId={this.props.location.state.reportId}
optionsForBackButton={this.props.location.state.comments}
/>
</View>
</View>
)
}
}
export default withRouter(Comment)
const CommentList = ({options, currentUser, history, reportId, optionsForBackButton}) => {
return (
<View>
{options.map(option => (
<View
style={{flexDirection: 'row'}}
>
<NativeText
style={{fontSize: 12, fontFamily: 'Montserrat-Regular'}}
>
{option.content}
</NativeText>
<View
style={{flex: 1, alignItems: 'flex-end' }}
>
<Icon
name='reply'
size={12}
// onPress={() => {
// setModalVisible(true)
// changeParentId(option._id)
// }}
onPress={() => history.push({pathname: '/create-comment', state: {content: option.content, currentUser: currentUser, reportId: reportId, parentCommentId: option._id, optionsForBackButton: optionsForBackButton}})}
/>
</View>
{
<View
style={{left: '10%'}}
>
<CommentList
options={option.reply}
optionsForBackButton={optionsForBackButton}
history={history}
currentUser={currentUser}
reportId={reportId}
/>
</View>
}
</View>
))}
</View>
)
}
Set your icon containing view's flex value to 1. This should cause it to fill all remaining space.
See the following snack: https://snack.expo.io/#jrdndncn/playful-churros
class Comment extends React.Component {
render() {
return (
<View
style={{
marginVertical: 2,
flexDirection: 'row',
marginLeft: (this.props.indent || 0) * 20,
}}>
<Text>{this.props.text}</Text>
<View style={{ flex: 1, alignItems: 'flex-end' }}>
<View style={{ width: 20, height: 20, backgroundColor: 'red' }} />
</View>
</View>
);
}
}
<Comment text="hello" indent={0} />
<Comment text="hello" indent={1} />
<Comment text="hello" indent={2} />
Basically marginLeft:'auto' will do the trick. just add style to icon as :
<Icon
name='reply'
size={12}
style={{marginLeft:'auto'}}
// onPress={() => {
// setModalVisible(true)
// changeParentId(option._id)
// }}
onPress={() => history.push({pathname: '/create-comment', state: {content: option.content, currentUser: currentUser, reportId: reportId, parentCommentId: option._id, optionsForBackButton: optionsForBackButton}})}
/>
i added marginLeft:'auto' in style it will automatically shown at the right end of the screen.

How to fix keyboard from hiding input fields in React Native

I’m setting up a new component,
and the keyboard covers the fields
This is for a new component
<KeyboardAwareScrollView enableOnAndroid={true} extraScrollHeight={50} enableAutomaticScroll={true}>
<View style={{ paddingHorizontal: 20 }}>
<View>
<FloatingLabelInput
onRef={(ref) => {
this.inputs['firstName'] = ref
}}
onSubmitEditing={() => {
this.focusNextField('lastName')
}}
label={i18n.t('t_driver_registration_first_name_label')}
onChangeText={(text) => this.onChangeInputText('firstName', text)}
keyboardType='default'
maxLength={20}
value={form.firstName}
labelStyle={Style.inputLabel}
basicColor={GStyle.GREEN}
inputTextColor={Color(GStyle.BLACK).alpha(.7)}
editable={mode !== DriverFormMode.EDIT}
/>
I expect the keyboard will not cover my fields.
Wrap your view in this to scroll automatically on input focus. Do:
<KeyboardAvoidingView style={{ flex: 1, flexDirection: 'column',justifyContent: 'center',}} behavior="padding" enabled keyboardVerticalOffset={100}>
<ScrollView>
<View style={Styles.row}>
//your view
</View>
</ScrollView>
</KeyboardAvoidingView>
<View style={Styles.row}> This is just a Stylesheet e.g. Create a new StyleSheet:
const Styles = StyleSheet.create({
row: {
borderRadius: 4,
borderWidth: 0.5,
borderColor: '#d6d7da',
},
title: {
fontSize: 19,
fontWeight: 'bold',
},
activeTitle: {
color: 'red',
},
});
Use a StyleSheet:
<View style={Styles.row}>
<Text style={[Styles.title, this.props.isActive && styles.activeTitle]} />
</View>

How to add extra item at the bottom of the drawer navigation manually (like logout button)?

I want to add logout button to the bottom of the drawer navigation in my RN app.
I am trying to use contentComponent the following way:
const DrawerWithLogoutButton = (props) => (
<ScrollView>
<SafeAreaView style={styles.container} forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItems {...props} />
</SafeAreaView>
<Button
style={styles.logoutButton}
title="Logout"
onPress={() => props.navigation.navigate('Login') }/>
</ScrollView>
);
export default Home = createDrawerNavigator({
// screens
}, {
// other settings
contentComponent: DrawerWithLogoutButton,
});
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
},
logoutButton: {
backgroundColor: 'red',
position: 'absolute',
bottom: 0
}
});
In the result I have the Logout button at the bottom of the menu. But I want it to be located at the bottom of the drawer panel instead
Also I would want the Logout button to look like other menu items and had an icon
Is there a way to create drawer navigator with a menu item which has no screen but is just an action like Logout as in my case?
I was able to align Logout at the bottom of the drawer menu with adding justifyContent: 'space-between' to the ScrollView container. You can see the result in the picture
The result source code looks the following way:
const DrawerWithLogoutButton = (props) => (
<ScrollView contentContainerStyle={{flex: 1, flexDirection: 'column', justifyContent: 'space-between' }}>
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItems {...props} />
</SafeAreaView>
<TouchableOpacity>
<View style={styles.item}>
<View style={styles.iconContainer}>
<Image source={require('./img/logout.png')} style={styles.icon}></Image>
</View>
<Text style={styles.label}>Logout</Text>
</View>
</TouchableOpacity>
</ScrollView>
);
const styles = StyleSheet.create({
item: {
flexDirection: 'row',
alignItems: 'center',
},
label: {
margin: 16,
fontWeight: 'bold',
color: 'rgba(0, 0, 0, .87)',
},
iconContainer: {
marginHorizontal: 16,
width: 24,
alignItems: 'center',
},
icon: {
width: 24,
height: 24,
}
});
React Navigation docs recommend wrapping the drawer navigation with a custom content drawer function. This is what we do did to give our drawer a logout button, but also keep all of the Drawer.Screens in place.
In the code below we create a CustomDrawerContent that contains a DrawerItem as our logout button. This function wraps the Drawer.Navigator through its property drawerContent. Our final drawer then looks like:
Home (Drawer.Screen)
Edit Profile (Drawer.Screen)
Landing (Drawer.Screen)
Logout (DrawerItem)
const Drawer = createDrawerNavigator();
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
<DrawerItem label={() => <Text style={{ color: 'white' }}>Logout</Text>}
style={{backgroundColor: 'red'}}
onPress={() => alert('Logged out')}
/>
</DrawerContentScrollView>
);
}
function App(props) {
return (
<Provider store={store}>
<View style={styles.container}>
<StatusBar translucent={true} />
<NavigationContainer>
<Drawer.Navigator drawerContent={props => <CustomDrawerContent {...props} />}>
<Drawer.Screen name='Home' component={Home} />
<Drawer.Screen name='Edit Profile' component={EditProfile} />
<Drawer.Screen name='Landing' component={Landing} />
</Drawer.Navigator>
</NavigationContainer>
</View>
</Provider>
)
}
Similar to William Griffins answer, except their answer does not end up with the logout button at the bottom of the drawer. To have logout be at the bottom, I put my DrawerContentScrollView inside a SafeAreaView, then beneath the DrawerContentScrollView I put a regular View containing the DrawerItem, which is the logout button.
function CustomDrawerContent(props) {
return (
<SafeAreaView style={{flex: 1}} forceInset={{top: "always", horizontal: "never"}}>
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
</DrawerContentScrollView>
<View>
<DrawerItem label={"Logout"}
style={styles.logoutDrawerItem}
onPress={() => console.log('Logout pressed!')}
/>
</View>
</SafeAreaView>
);
}
function App(props) {
return (
<Provider store={store}>
<View style={styles.container}>
<StatusBar translucent={true} />
<NavigationContainer>
<Drawer.Navigator drawerContent={props => <CustomDrawerContent {...props} />}>
<Drawer.Screen name='Home' component={Home} />
<Drawer.Screen name='Edit Profile' component={EditProfile} />
<Drawer.Screen name='Landing' component={Landing} />
</Drawer.Navigator>
</NavigationContainer>
</View>
</Provider>
)
}
const styles = StyleSheet.create({
logoutDrawerItem: {
borderRadius: 5,
},
});
Any items you place beneath the DrawerContentScrollView will be placed at the bottom of the drawer.
Note that I set borderRadius to 5 on the logout DrawerItem, so that it closely matches the border radius of regular drawer items.
You can set position:'absolute' and buttom:0 like this code:
<TouchableOpacity
onPress={() => {this.logout()}}
style={{ bottom: 0, position: 'absolute', width: '100%' }}>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', flexDirection:'row', alignItems: 'center' }}>
<Icon name="md-log-out" style={{marginRight: 10, color: '#444'}} size={20}/>
<Text style={{color: '#444'}}>Logout</Text>
</View>
</TouchableOpacity>
You can change the style to make it like other buttons. I hope this will help you...
The accepted answer did not work out for me directly. I had to do some modifications, but in general the secret is indeed using justifyContent: 'space-between'.
import {View} from 'react-native';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItem,
DrawerItemList,
DrawerContentComponentProps,
} from '#react-navigation/drawer';
const Drawer = createDrawerNavigator();
function CustomDrawerContent(props: DrawerContentComponentProps) {
return (
<DrawerContentScrollView
{...props}
contentContainerStyle={{flex: 1, justifyContent: 'space-between'}}>
<View style={{justifyContent: 'flex-start'}}>
<DrawerItemList {...props} />
</View>
<DrawerItem
label="Logout"
onPress={() => console.log('Logged out')}
/>
</DrawerContentScrollView>
);
}
.
.
.
<Drawer.Navigator
initialRouteName="HomeScreen"
drawerContent={(props) => <CustomDrawerContent {...props} />}
drawerContentOptions={{
activeTintColor: color.primaryDark,
itemStyle: {
backgroundColor: 'transperant',
borderColor: color.primaryDark,
borderBottomWidth: 1,
opacity: 0.8,
},
}}
drawerStyle={styles.drawer}>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>

React Native View

Hello I am new to react native and i am having problems with the view. I am having trouble with the text input as it only shows very small. When i
remove the container in the StyleSheet All Text disappears and the text inputs become big.
Here is my code
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.android.js
</Text>
<Text style={styles.instructions}>
Double tap R on your keyboard to reload,{'\n'}
Shake or press menu button for dev menu
</Text>
<View>
<View style ={styles.textinput}>
<TextInput
keyboardType='ascii-capable'
placeholder='First Name'
value={this.state.firstName}
onChangeText={(text) => {this.setState({firstName: text})}}/>
<TextInput
keyboardType='ascii-capable'
placeholder='Middle Name'
value={this.state.middleName}
onChangeText={(text) => {this.setState({middleName: text})}}/>
<TextInput
keyboardType='ascii-capable'
placeholder='Last Name'
value={this.state.lastName}
onChangeText={(text) => {this.setState({lastName: text})}}/>
<TextInput
keyboardType='ascii-capable'
placeholder='Email'
value={this.state.email}
onChangeText={(text) => {this.setState({email: text})}}/>
<TextInput
keyboardType='ascii-capable'
placeholder='Address'
value={this.state.address}
onChangeText={(text) => {this.setState({address: text})}}/>
</View>
<View style={styles.buttonModal}>
<Button
style={styles.cancelButton}
onPress={this.editUser}
title="SAVE"
color="#343434"
accessibilityLabel="Save user."/>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
textinput: {
flex: 0,
},
buttonModal: {
paddingTop: 20,
flexDirection: 'row',
justifyContent: 'space-around'
},
});
Remove <view> above <View style ={styles.textinput}> and make
textinput: {
flex: 1,
}
for button, try by commenting flexDirection: 'row',justifyContent: 'space-around' one by one.