I am a newbie in react native. I tried to create a to-do app, simple enough. But I have no idea why the text in the created to-do item not rendered
import React, { useState } from 'react';
import {
StyleSheet,
Text,
View,
Button,
TextInput,
FlatList,
Dimensions
} from 'react-native';
export default function App() {
const [task, setTaskText] = useState('')
const [tasks, setTasks] = useState([])
const addTask = () => {
setTasks([...tasks, { key: Math.random().toString(), text: task}])
}
return (
<View style={styles.container}>
<View style={styles.form}>
<TextInput
onChangeText={setTaskText}
value={task}
placeholder="Type a task..."
style={styles.input}
multiline
/>
<Button title="Add Task" style={styles.button} onPress={addTask} />
</View>
<FlatList
style={styles.itemContainer}
data={tasks}
renderItem={itemData => (
<View style={styles.taskItem}>
<Text style={styles.taskText}>{itemData.text}</Text><Button title="Complete" />
</View>
)}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 32,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
form: {
// flex: 1,
flexDirection: 'row',
padding: 32,
justifyContent: 'space-between',
},
button: {
fontSize: 32,
padding: 5
},
tasks: {
flex: 1,
alignContent: 'flex-start',
},
input: {
flex: 1,
fontSize: 22,
},
itemContainer: {
flex: 1,
width: Dimensions.get('window').width,
padding: 20,
borderColor: 'red',
borderWidth: 1
},
taskItem: {
padding: 10,
borderColor: 'black',
borderWidth: 1,
backgroundColor: '#efefef',
marginBottom: 10,
alignContent: 'center',
justifyContent: 'center',
flexDirection: 'row'
},
taskText: {
flex: 1,
fontSize: 24,
borderColor: 'yellow',
borderWidth: 1,
color: 'black',
textAlign: 'left'
}
});
So I tried to use a flat list and gave some border color to pin point the component rendered. I could see that the text component was rendered but there is no content
Can anyone help? What went wrong?
Your implementation was wrong.
It should be renderItem({item, index, separators})
And for each of the item you should consume it like item.text
<FlatList
style={styles.itemContainer}
data={tasks}
renderItem={ ({item}) => (
<View style={styles.taskItem}>
<Text style={styles.taskText}>{item.text}</Text><Button title="Complete" />
</View>
)}
/>
Related
I cannot click the 1st and 2nd item because there is text input behind it and 3rd and 4th item because of the button behind it. 5th item is clickable. I tried using zindex but it does not work. I am using react-native-autocomplete-input library.
It works fine in iOS but not in Android
This is my code
import Autocomplete from 'react-native-autocomplete-input';
import {
GestureHandlerRootView,
TouchableOpacity as Touchable,
} from 'react-native-gesture-handler';
<View style={[styles.inputContainer, globalStyles.zIndex1]}>
<Text style={styles.inputLabel}>{getSupplierLabel()}</Text>
<Autocomplete
editable={true}
autoCorrect={false}
data={filteredParties}
onChangeText={(text: string) => {
//some code
}}
value={party}
flatListProps={{
keyboardShouldPersistTaps: 'always',
keyExtractor: (party: any) => party.id,
renderItem: ({item: {name}}: any) => (
<Touchable
style={[globalStyles.margin10, globalStyles.zIndex1]}
onPress={() => {
setFilteredParties([]);
setParty(name);
}}>
<Text textColor={color.gray}>{name}</Text>
</Touchable>
),
}}
inputContainerStyle={globalStyles.borderWidth0}
listContainerStyle={styles.autocompleteListContainerStyle}
containerStyle={styles.textInput}
/>
const styles = StyleSheet.create({
inputContainer: {
flexDirection: 'row',
alignItems: 'center',
marginTop: 10,
},
textInput: {
flex: 2,
borderWidth: 1,
borderColor: color.gray,
borderRadius: 2,
marginLeft: 5,
},
autocompleteListContainerStyle: {
left: 0,
position: 'absolute',
right: 0,
top: 41,
zIndex: 1,
},
});
Wrap your AutoComplete component with a view and give it a suitable zIndex :
import Autocomplete from 'react-native-autocomplete-input';
import {
GestureHandlerRootView,
TouchableOpacity as Touchable,
} from 'react-native-gesture-handler';
<View style={[styles.inputContainer, globalStyles.zIndex1]}>
<Text style={styles.inputLabel}>{getSupplierLabel()}</Text>
<View style={ zIndex: 2 }>
<Autocomplete
editable={true}
autoCorrect={false}
data={filteredParties}
onChangeText={(text: string) => {
//some code
}}
value={party}
flatListProps={{
keyboardShouldPersistTaps: 'always',
keyExtractor: (party: any) => party.id,
renderItem: ({item: {name}}: any) => (
<Touchable
style={[globalStyles.margin10, globalStyles.zIndex1]}
onPress={() => {
setFilteredParties([]);
setParty(name);
}}>
<Text textColor={color.gray}>{name}</Text>
</Touchable>
),
}}
inputContainerStyle={globalStyles.borderWidth0}
listContainerStyle={styles.autocompleteListContainerStyle}
containerStyle={styles.textInput}
/>
</View>
const styles = StyleSheet.create({
inputContainer: {
flexDirection: 'row',
alignItems: 'center',
marginTop: 10,
},
textInput: {
flex: 2,
borderWidth: 1,
borderColor: color.gray,
borderRadius: 2,
marginLeft: 5,
},
autocompleteListContainerStyle: {
left: 0,
position: 'absolute',
right: 0,
top: 41,
zIndex: 1,
},
});
this is my profile page I want scroll animation but I didn't get output
** there is two-part one is header and body part is fully based on card view **
import React, { useRef } from 'react';
import {
StyleSheet,
Text,
View,
Image,
Animated,ScrollView
} from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';
import {Card, Title, Paragraph } from 'react-native-paper';
import { MaterialCommunityIcons } from '#expo/vector-icons';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import SafeAreaView from 'react-native-safe-area-view';
import AnimatedHeader from 'C:\Users\keerthana\Desktop\mobile-client-1\src\components\AnimatedHeader.js';
const SettingsScreen=()=>{
const offset = useRef(new Animated.Value(0)).current;
return ( <SafeAreaProvider>
<SafeAreaView style={{ flex: 1 }} forceInset={{ top: 'always' }}>
<AnimatedHeader animatedValue={offset} />
<ScrollView
style={{ flex: 1, backgroundColor: 'white' }}
contentContainerStyle={{
alignItems: 'center',
paddingTop: 220,
paddingHorizontal: 20
}}
showsVerticalScrollIndicator={false}
scrollEventThrottle={16}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: offset } } }],
{ useNativeDriver: false }
)}
>
<View style={styles.header}>
<View style={styles.headerContent}>
<Image style={styles.avatar} source={{uri: 'https://bootdey.com/img/Content/avatar/avatar2.png'}}/>
<Text style={styles.name}>
Name
</Text>
</View>
<View style={{ backgroundColor: "#FFF"}}>
<Card style={{padding:5,borderWidth: 1,borderRadius: 1,borderColor: '#adacac',marginTop:20}}>
<Card.Title title="INFO" subtitle="username" />
<Card.Content>
<Title style={{fontSize:16}}>Phone Number</Title>
<Paragraph>0000000000000</Paragraph>
</Card.Content>
<Card.Content style={{borderWidth: 0, borderColor: 'transparent', elevation: 0}}>
<Title style={{fontSize:16}}>Slogan</Title>
<Paragraph >Testing leads to failure, and failure leads to understanding</Paragraph>
</Card.Content>
</Card>
<Card style={{padding:5,borderWidth: 1,borderRadius: 1,borderColor: '#adacac',marginTop:10}}>
<Card.Title title="Groups" />
</Card>
<View style={{padding:5,borderWidth: 1,borderRadius: 1,borderColor: '#adacac',marginTop:10}}>
//group
<TouchableOpacity>
<View style={{flex: 1,justifyContent: 'center',marginLeft:20}}>
<Image
width={450}
containerStyle={{flex: 0.37}}
imageProps={{resizeMode:'cover'}}
source={{uri: 'https://bootdey.com/img/Content/avatar/avatar2.png'}}
activeOpacity={0.7}
/>
</View>
<View style={{flex: 11,flexDirection: 'column',justifyContent: 'center'}}>
<View style={{ flexDirection: 'row',justifyContent: 'flex-start', marginLeft: 9 }}>
<Text >music game</Text>
</View></View>
</TouchableOpacity>
<TouchableOpacity>
<Text>ludo game</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text> game</Text>
</TouchableOpacity>
</View>
</View>
</View>
</ScrollView>
</SafeAreaView>
</SafeAreaProvider>
);
};
export default SettingsScreen;
const styles=StyleSheet.create({
header:{
backgroundColor: "#e6e3e3",
},
headerContent:{
padding:30,
alignItems: 'center',
},
avatar: {
width: 130,
height: 130,
borderRadius: 63,
borderWidth: 4,
borderColor: "white",
marginBottom:10,
},
name:{
fontSize:22,
color:"#FFFFFF",
fontWeight:'600',
},
profileDetail:{
alignSelf: 'center',
marginTop:200,
alignItems: 'center',
flexDirection: 'row',
position:'absolute',
backgroundColor: "#ffffff"
},
detailContent:{
margin:10,
alignItems: 'center'
},
title:{
fontSize:20,
color: "#00CED1"
},
count:{
fontSize:18,
},
bodyContent: {
flex: 1,
alignItems: 'center',
padding:30,
marginTop:40
},
textInfo:{
fontSize:18,
marginTop:20,
color: "#696969",
},
buttonContainer: {
marginTop:10,
height:45,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom:20,
width:250,
borderRadius:30,
backgroundColor: "#00CED1",
},
description:{
fontSize:20,
color: "#00CED1",
marginTop:10,
textAlign: 'center'
},
});
animation page
** this animation is used for profile page scroll **
import React from 'react';
import {
Animated,
TouchableOpacity,
View,
Text,
StyleSheet
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
const HEADER_HEIGHT = 200;
const AnimatedHeader = ({ animatedValue }) => {
const insets = useSafeAreaInsets();
const headerHeight = animatedValue.interpolate({
inputRange: [0, HEADER_HEIGHT + insets.top],
outputRange: [HEADER_HEIGHT + insets.top, insets.top + 44],
extrapolate: 'clamp'
});
return (
<Animated.View
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
zIndex: 10,
height: headerHeight,
backgroundColor: 'lightblue'
}}
/>
);
};
export default AnimatedHeader;
without using the animation part its works properly but after adding animation I don't know why it's not working.
I am trying to create a side drawer only for one screen hence am using react-native-side-drawer as per the documentation in https://www.npmjs.com/package/react-native-side-drawer, however when I try to rerender it my screen is showing up blank as follows:
Below is my exact and complete code:
import React, {useEffect, useState} from 'react';
import {
View,
ScrollView,
ActivityIndicator,
Text,
TouchableOpacity,
StyleSheet,
Image,
} from 'react-native';
import MenuDrawer from 'react-native-side-drawer';
export default function HomeTabScreen(props) {
const {navigation} = props;
const [loading, setLoading] = useState(false);
// side drawer
const [open, setOpen] = useState(false);
useEffect(() => {
// console.log('useEffect - user', User);
// console.log('useEffect - mSChildId', mSChildId);
if (isValidObject(User) && isValidObject(mSChildId)) {
console.log('useEffect true');
console.log('useEffect true - user', User);
if (loadApi == true) {
getHomeTabMainAPI();
setLoadApi(false);
setSelectedChild(getChildFromUserChildrenList());
}
} else {
console.log('useEffect false');
if (!isValidObject(User) || !isValidObject(mSChildId)) {
console.log(
'!!!!!! Calling get user data !!!! Child Id ',
mSChildId,
' User Valid ',
isValidObject(User),
);
getUserData();
}
}
}, [User, mSChildId, loadApi]);
const toggleOpen = () => {
setOpen(!open);
};
const drawerContent = () => {
return (
<TouchableOpacity
style={{
marginLeft: '80%',
}}
onPress={() => logoutHandler()}>
<Text style={{fontSize: 15, fontWeight: 'bold', color: '#000'}}>
Log out
</Text>
</TouchableOpacity>
);
};
return (
<SafeAreaView
style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
{loading ? (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<ActivityIndicator size="large" color="#FE017E" />
</View>
) : (
<ScrollView showsVerticalScrollIndicator={false}>
<View
style={{
flex: 1,
backgroundColor: '#fff',
flex: 1,
alignItems: 'center',
justifyContent: 'center',
}}>
<MenuDrawer
open={open}
drawerContent={drawerContent()}
drawerPercentage={45}
animationTime={250}
overlay={true}
opacity={0.4}>
<View
style={{
backgroundColor: '#fff',
padding: 10,
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<TouchableOpacity onPress={() => toggleOpen()}>
<Icon size={15} name="bars" />
</TouchableOpacity>
<TouchableOpacity
style={{
marginLeft: '80%',
}}
onPress={() => logoutHandler()}>
<Text
style={{fontSize: 15, fontWeight: 'bold', color: '#000'}}>
Log out
</Text>
</TouchableOpacity>
</View>
<View>
renders more stuff here.....that should show up on the screen
</View>
</MenuDrawer>
</View>
</ScrollView>
)}
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
marginTop: 30,
zIndex: 0,
},
animatedBox: {
flex: 1,
backgroundColor: '#38C8EC',
padding: 10,
},
body: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#F04812',
},
});
Any help would be appreciated, please let me know where I have gone wrong.
P.S: I am getting all the data on my console, but not on the screen
Look at my code below please I am trying to find a way to make a delete button but i am very new to react native, i have been trying to do it for the past few hours.
import React, { useState } from 'react';
import { StyleSheet, FlatList, Text, View, Image, TextInput, Button, Keyboard, TouchableOpacity, CheckBox } from 'react-native';
import Interactable from 'react-native-interactable';
export default function App()
const [enteredGoal, setEnteredGoal] = useState('');
const [courseGoals, setCourseGoals] = useState([]);
const goalInputHandler = (enteredText) => {
setEnteredGoal(enteredText);
};
const addGoalHandler = () => {
if (enteredGoal.length > 0) {
setCourseGoals(currentGoals => [...currentGoals, enteredGoal])
} else {
alert("You have to write something!")
}
}
return (
<View style={styles.container}>
<View style={styles.topPart}></View>
<View style={styles.navBar}>
<Image source={require('./assets/baseline_menu_black_18dp.png/')} />
<Text style={styles.heading}> Grocery List </Text>
</View>
<View style={styles.body}>
<TextInput
style={styles.textInput}
placeholder='Groceries'
maxLength={20}
onBlur={Keyboard.dismiss}
value={enteredGoal}
onChangeText={goalInputHandler}
/>
<View style={styles.inputContainer}>
<TouchableOpacity style={styles.saveButton}>
<Button title="ADD" onPress={addGoalHandler} color="#FFFFFF" style={styles.saveButtonText} />
</TouchableOpacity>
</View>
<View style={styles.container}>
<FlatList
data={courseGoals}
renderItem={itemData => (
<View style={styles.groceryItem} >
<Text style={styles.groceryItemText}>{itemData.item}</Text>
<Text style={styles.groceryItemDelete}>X</Text>
</View>
)}
/>
</View>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
topPart: {
height: '3%',
backgroundColor: '#5498A7',
},
navBar: {
height: '10%',
backgroundColor: '#5498A7',
elevation: 3,
paddingHorizontal: 15,
flexDirection: 'row',
alignItems: 'center',
},
body: {
backgroundColor: '#edebe9',
height: '100%',
flex: 1
},
heading: {
fontWeight: "bold",
justifyContent: 'center',
paddingLeft: '13%',
fontSize: 25,
color: '#d6d4d3'
},
textInput: {
borderColor: '#CCCCCC',
borderTopWidth: 1,
borderBottomWidth: 1,
height: 50,
fontSize: 25,
paddingLeft: 20,
paddingRight: 20
},
saveButton: {
borderWidth: 1,
borderColor: '#5498A7',
backgroundColor: '#5498A7',
padding: 15,
margin: 5,
},
saveButtonText: {
color: '#FFFFFF',
fontSize: 20,
textAlign: 'center'
},
groceryItem: {
borderWidth: 1,
borderColor: 'black',
backgroundColor: '#6A686B',
padding: 15,
margin: 5,
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between'
},
groceryItemText: {
color: '#d6d4d3',
},
groceryItemDelete: {
color: 'red',
fontWeight: 'bold',
fontSize: 20
}
});
I hope you guys can find a solution I will keep u guys updated on my progress, I am constantly looking for answers but i don't really understand how to make the delete (X) work and to make it delete a different element, if you know a way to make work better just let me know i would appreciate it a lot
You have to send index to delete function.
renderItem={(itemData,index) => (
<View style={styles.groceryItem} >
<Text style={styles.groceryItemText}>{itemData.item}</Text>
<Text style={styles.groceryItemDelete.bind(index)}>X</Text>
</View>
and example delete function :
groceryItemDelete(index){
setCourseGoals(currentGoals.splice(index,1))
}
You need to implement the delete method and add an onPress event:
renderItem={(itemData, idx) => (
<View style={styles.groceryItem} >
<Text style={styles.groceryItemText}>{itemData.item}</Text>
<Text style={styles.groceryItemDelete} onPress={() => deleteItem(idx)}>X</Text>
</View>
)}
const deleteItem = idx => {
const clonedGoals = [...courseGoals]
clonedGoals.splice(idx, 1)
setCourseGoals(clonedGoals)
}
My Tag Component, which consist out of rendered texts and a text input component, renders under another component, my button and behaves super weird.
If you look at the gif you can also see, that the tags from the second line onwards are not getting wrapped by my container style as well.
I made a gif, which should make it easier to see :)
http://www.giphy.com/gifs/JmD2VWAXU3S12LQ0Ya
const styles = StyleSheet.create({
textInput: {
flex: 1,
borderRadius: 8,
paddingLeft: 9,
paddingRight: 9,
height: 30,
marginRight: 15,
},
tagContainer: {
flexDirection: 'row',
flexWrap: 'wrap'
},
tags: {
backgroundColor: "#9AA5B1",
borderRadius: 8,
paddingLeft: 9,
paddingRight: 9,
paddingTop: 4,
paddingBottom: 4,
marginRight: 10,
marginBottom: 4,
flexDirection: "row",
},
text: {
color: "white",
},
container: {
backgroundColor: '#F5F7FA',
borderRadius: 8,
paddingLeft: 9,
paddingRight: 9,
height: 30,
marginRight: 15,
flexDirection: "row",
flexWrap: "wrap",
},
});
renderTags1 = (tag, index, deleteTag) => {
return (
<TouchableOpacity
onPress={index => deleteTag(index)}
style={styles.tags}
key={`${tag}-${index}`}
>
<Text style={styles.text}>{tag}</Text>
</TouchableOpacity>
);
};
const InputTags = ({ tags, value, onChangeText, deleteTag }) => {
return (
<View style={styles.container}>
<View style={styles.tagContainer}>
{tags.map((tag, index) => {
return this.renderTags1(tag, index, deleteTag);
})}
</View>
<TextInput
style={styles.textInput}
placeholder="Outdoor"
onChangeText={text => onChangeText({ text })}
value={value}
autoCorrect={false}
multiline={true}
/>
</View>
);
};
export { InputTags };
For my Button :
import React from 'react';
import { Text, TouchableOpacity, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
view: {
backgroundColor: '#E12D39',
width: 280,
height: 50,
justifyContent: 'center',
alignSelf: 'center',
borderRadius: 10,
marginTop: 40,
marginBottom: 40,
},
text: {
alignSelf: 'center',
fontFamily: 'OpenSans-Semibold',
fontSize: 22,
color: 'white',
},
});
const SearchButton = ({ onPress, text }) => {
return (
<TouchableOpacity style={styles.view} onPress={onPress}>
<Text style={styles.text}>{text}</Text>
</TouchableOpacity>
);
};
export { SearchButton };
Expected behavior is for the Button to go down. Tried to remove every single flex property, but could not quite figure it out yet
seems like the height is not increasing when it wraps, could confirm it by making the container bg a different color
Looks like you hard coded the height to be 30, which is probably causing the bug