React Native Flatlist ListHeaderComponent Doesn't Work - react-native

ListHeaderComponent inside flatlist doesn't work. It won't render nothing in header (above flatlist). If I however put some custom component it does work but it doesn't with my renderHeader function. I tried making a custom component with the same view as in renderHeader but when I used that nothing rendered so I don't know
My flatlist along with whole render:
render() {
const { height } = Dimensions.get("window");
return (
<View style={{flex: 1,
backgroundColor: "#EBECF4"}}>
{/* <Text>
Connection Status :{" "}
{this.state.connection_status ? "Connected" : "Disconnected"}
</Text> */}
{/* <Loader loading={this.state.loading} /> */}
<StatusBar backgroundColor="#63003d" barStyle="light-content" />
<SafeAreaView>
<ModernHeader
backgroundColor="#63003d"
height={50}
text="Eleph"
textStyle={{
color: "white",
fontFamily: "Lobster-Regular",
//fontWeight: "bold",
fontSize: 25,
}}
leftIconComponent={
<TouchableOpacity
style={{ marginRight: 0, margin: 0 }}
onPress={() =>
this.props.navigation.dispatch(DrawerActions.openDrawer())
}
>
<FontAwesome5 name="bars" size={22} color="white" />
</TouchableOpacity>
}
rightIconComponent={
<TouchableOpacity
style={{ marginLeft: 0, margin: 0 }}
onPress={() => this.props.navigation.navigate("Profile")}
>
{/* <MaterialCommunityIcons
name="chart-areaspline"
size={24}
color="#639dff"
/> */}
<Foundation name="graph-bar" size={24} color="white" />
{/* <FontAwesome name="bar-chart" size={24} color="white" /> */}
</TouchableOpacity>
}
/>
</SafeAreaView>
<FlatList
//contentInset={{ top: HEADER_HEIGHT }}
//contentOffset={{ y: -HEADER_HEIGHT }}
data={this.state.post}
extraData={this.state.post}
keyExtractor={(item) => item.id.toString()}
style={{
marginHorizontal: 0,
marginVertical: 6,
}}
renderItem={({ item }) => this.renderPost(item)}
ListFooterComponent={this.renderFooter}
ListHeaderComponent={this.renderHeader}
refreshControl={
<RefreshControl
style={{ color: "#639dff" }}
tintColor="#639dff"
titleColor="#fff"
refreshing={this.state.isLoading}
onRefresh={this.onRefresh}
/>
}
initialNumToRender={7}
onEndReachedThreshold={0.1}
showsVerticalScrollIndicator={false}
onEndReached={() => {
if (
!this.onEndReachedCalledDuringMomentum &&
!this.state.isMoreLoading
) {
this.getMore();
}
}}
onMomentumScrollBegin={() => {
this.onEndReachedCalledDuringMomentum = false;
}}
onScroll={(e) => {
scrollY.setValue(e.nativeEvent.contentOffset.y);
}}
></FlatList>
{/* <View style={styles.footer}>
<TouchableOpacity
activeOpacity={0.9}
onPress={this.getMore}
style={styles.loadMoreBtn}
>
<Text style={styles.btnText}>See more moods</Text>
{this.state.loading ? (
<ActivityIndicator color="white" style={{ marginLeft:8 }} />
) : null}
</TouchableOpacity>
</View> */}
</SafeAreaView>
</View>
My renderHeader function:
renderHeader = () => {
return (
<View
style={{
flex: 1,
flexDirection: "row",
backgroundColor: "#ffffff",
//width: "100%",
padding: 11,
alignItems: "center",
position: "absolute",
justifyContent: "center",
//top: 50,
//bottom: 0,
//left: 0,
//elevation: 4,
//right: 0,
//height: 50,
}}
//flexDirection: "row",
//backgroundColor: "#ffffff",
//width: "100%",
//padding: 11,
//alignItems: "center",
>
<TouchableOpacity
onPress={() => this.props.navigation.navigate("Post")}
>
<Text
style={{ alignItems: "center", color: "#C4C6CE" }}
//placeholder={How are you feeling right now ${this.state.user.name}?}
multiline
>{Tell us how are you feeling right now ${this.state.user.name}?}</Text>
</TouchableOpacity>
{/* <View style={styles.divider}></View> */}
</View>
);
}
Why for example renderFooter works??
renderFooter = () => {
if (!this.state.isMoreLoading) return true;
return (
<ActivityIndicator
size="large"
color={"#D83E64"}
style={{ marginBottom: 10 }}
/>
);
};

Use ListHeaderComponentStyle to style the ListHeaderComponent.

I created a simple snack for you, check if this helps. Your code looks okay but not sure about the whole screen design. Here is my snack link.
https://snack.expo.io/#saad-bashar/excited-fudge
It might be related to the other components inside your screen. So first check only with flatlist, remove all other components. Hope you can sort it out :)

The solution is to remove the "absolute" style in the header for flatlist. The question is mine im just answering with different account but this is the solution that worked.

Related

React native password show hide

I need to show hide my password on eye click.
Right now I am trying to do like this
const [showPassword, setShowPassword] = useState(false)
<View style={styles.SectionStyle}>
<Text style={styles.textStyle} >Password</Text>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<TextInput
style={styles.inputStyle}
onChangeText={password => setPassword(password)}
underlineColorAndroid="#FFFFFF"
placeholderTextColor="grey"
secureTextEntry={showPassword}
placeholder="Must be at least 6 characters"
// ref={ref => {
// this._addressinput = ref;
// }}
// onSubmitEditing={Keyboard.dismiss}
blurOnSubmit={true}
/>
<TouchableOpacity onPress={() => setShowPassword(showPassword = !showPassword)}>
<Image
source={require('./../../../public/icons/Hide.png')}
style={{
position: 'absolute',
right: 0,
top: -2,
marginRight: 16,
// marginTop: 30,
width: 16,
height: 16
}}
/>
</TouchableOpacity>
</View>
</View>
But it's not working I am doing something wrong? I think need to do something in state?
the setShowPassword accepts an arrow function as arguments with the state as params
So it should be like this:
<TouchableOpacity onPress={() => setShowPassword(showPassword => !showPassword)}>

React native react-native-google-places-autocomplete VirtualizedLists warning

I created a form in which I have a field called address. Where I implemented 'react-native-google-places-autocomplete' plugin. It's working fine if I don't add scrollView. But I need to add scrollView just because I have so many input fields inside that form. but then I got a warning "VirtualizedLists should never be nested inside plain ScrollViews with the same orientation".
Here is my code:
Add.js
<SafeAreaView style={{ flex: 1, paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0, backgroundColor: 'white' }}>
<View style={{ flex: 1 }}>
<ScrollView scrollEventThrottle={16}>
<View style={{ flex: 1 }}>
<Text style={{ fontSize: 20, marginTop: 5, marginBottom: 10, paddingHorizontal: 15, fontFamily: 'Mulish-SemiBold' }}>Add Ground</Text>
<TouchableWithoutFeedback style={styles.button} onPress={(e) => this.chooseFile()}>
<Image source={this.state.avatarSource ? this.state.avatarSource : require('./../../assets/images/default-cover.jpg')} style={{ width: '100%', height: 150 }} />
</TouchableWithoutFeedback>
<View style={styles.inputWrapper}>
<Text style={styles.inputLabel}>Name</Text>
<TextInput
style={styles.input}
placeholder="e.g Drealit Stadium"
onChangeText={name => this.setState({ name })}
value={this.state.name}
autoCorrect={false}
/>
</View>
<View style={styles.inputWrapper}>
<Text style={styles.inputLabel}>Address</Text>
{/*
onChangeText={address => this.setState({ address })}
value={this.state.address}
*/}
<ScrollView>
<GooglePlacesInput />
</ScrollView>
</View>
<View style={styles.inputWrapper}>
<Text style={styles.inputLabel}>Contact Person Name</Text>
<TextInput
style={styles.input}
placeholder="e.g David Johnson"
onChangeText={organizer_name => this.setState({ organizer_name })}
value={this.state.organizer_name}
autoCorrect={false}
/>
</View>
<View style={styles.inputWrapper}>
<Text style={styles.inputLabel}>Contact Person Number</Text>
<TextInputMask
type={'cel-phone'}
options={{
maskType: 'INTERNATIONAL',
}}
placeholder="e.g 509-962-9014"
style={styles.input}
value={this.state.organizer_number}
onChangeText={organizer_number => this.setState({ organizer_number })}
/>
</View>
<View style={styles.inputWrapper}>
<Text style={styles.inputLabel}>Description</Text>
<TextInput
placeholder="e.g A Ground suitable for small side cricket tournament. Ideal for some fast paced cricket and lot of fun."
onChangeText={description => this.setState({ description })}
value={this.state.description}
autoCorrect={false}
multiline={true}
numberOfLines={4}
style={[styles.input, { height: 'auto', textAlignVertical: 'top' }]}
/>
</View>
<View style={styles.inputWrapper}>
<Text style={styles.inputLabel}>Rate per hour / day</Text>
<TextInput
style={styles.input}
placeholder="e.g 3500"
keyboardType="numeric"
onChangeText={ratePerHourDay => this.setState({ ratePerHourDay })}
value={this.state.ratePerHourDay}
autoCorrect={false}
/>
</View>
<View style={styles.inputWrapper}>
<Text style={styles.inputLabel}>Rate per hour / night</Text>
<TextInput
style={styles.input}
placeholder="e.g 4500"
keyboardType="numeric"
onChangeText={ratePerHourNight => this.setState({ ratePerHourNight })}
value={this.state.ratePerHourNight}
autoCorrect={false}
/>
</View>
<View style={{ marginHorizontal: 15, marginVertical: 10 }}>
<TouchableWithoutFeedback style={styles.button} onPress={(e) => this.manageAddGround(e)}>
<LinearGradient
colors={["#4678f6", "#4475ee", "#5053eb"]}
start={{ x: 0, y: 0 }}
end={{ x: 0, y: 0 }}
locations={[0, 0.5, 0.6]}
style={styles.appButtonContainer}
>
<Text style={styles.buttonText}>Save</Text>
</LinearGradient>
</TouchableWithoutFeedback>
</View>
</View>
</ScrollView>
</View>
</SafeAreaView>
GooglePlacesInput.js
<View style={{ flex: 1 }}>
<GooglePlacesAutocomplete
placeholder='e.g 640 Cross Creek Dr, Ellensburg, WA, 98926'
query={{
key: GOOGLE_PLACES_API_KEY,
language: 'en',
}}
enablePoweredByContainer={false}
onPress={(data, details = null) => {
console.log("GooglePlacesInput -> data", data)
}}
debounce={200}
styles={{
textInputContainer: {
backgroundColor: '#fff',
borderTopWidth: 0,
borderBottomWidth: 0,
},
textInput: {
marginLeft: 0,
marginRight: 0,
height: 40,
borderBottomWidth: 1,
color: '#000',
borderBottomColor: '#dedede'
},
predefinedPlacesDescription: {
color: '#1faadb',
},
listView: {
backgroundColor: '#fff',
borderWidth: 0.5,
borderColor: '#dedede',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 6,
},
shadowOpacity: 0.05,
shadowRadius: 10,
elevation: 4
}
}}
/>
</View>
You are receiving this warning because react-native-google-places-autocomplete renders a component to show results, and you have wrapped in a .
It's a warning, not an error. If it works for you can leave it as is.

react native Modal opening from last object in array

I am creating a render method where it displays information from a state array, and I want it so that when a user touches a Card a Modal will open presenting the same information.
My code is as follows:
this.state = {
fontLoaded: false,
feed: [{
username: ["Jeff", "Kyle", "David"],
caption: ["Great", "Amazing", "Not so Good"],
comments: ["Comment 1", "Comment 2", "No Comment"],
photo:[Pic1,Pic2,Pic3],
}]
}
state = {
isModalVisible: false,
};
toggleModal = () => {
this.setState({ isModalVisible: !this.state.isModalVisible });
};
renderFeed = () => {
return this.state.feed.map((card, index) => {
return card.username.map((username, i) => {
if(card.caption[i])
return (
<View>
<TouchableHighlight onPress={this.toggleModal} underlayColor="white">
<Card
key={`${i}_${index}`}
image={card.photo[i]}
containerStyle={{borderRadius:10, marginRight:1, marginLeft:1,}}>
<View
style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between' }}
>
<View style={{ flexDirection: 'row'}}>
<Avatar
size="small"
rounded
source={card.photo[i]}
/>
</View>
<View style={{flexDirection:'row'}}>
<Avatar
rounded
icon={{ name:'heart-multiple-outline', type:'material-community', color: '#ff4284'}}
overlayContainerStyle={{marginLeft:5}}
reverse
size='small'/>
<Avatar
reverse
rounded
icon={{ name:'comment-processing-outline', type:'material-community' }}
overlayContainerStyle={{backgroundColor: '#dbdbdb',marginLeft:5}}
size='small'/>
</View>
</View>
{ this.state.fontLoaded == true ? (
<View style={{flexDirection:'row'}}>
<Text style={{fontFamily: 'MontserratB', color:'#bf00b9', marginTop:10}}>{username}</Text>
<Text style={{fontFamily:'Montserrat', marginTop:10}}>{card.caption[i]}</Text>
</View>
) : (<Text> Loading...</Text>)
}
<Text style={{marginTop:4, color:'#878787'}}>{card.comments[i]}</Text>
</Card>
</TouchableHighlight>
<Modal
animationIn="zoomInDown"
animationOut="zoomOutDown"
animationInTiming={700}
animationOutTiming={600}
backdropTransitionInTiming={600}
backdropTransitionOutTiming={600}
isVisible={this.state.isModalVisible}>
<Image source={card.photo[i]}
style={{width: SCREEN_WIDTH - 20,
height: 300, justifyContent: 'center', alignSelf:
'center' }}/>
<Card
containerStyle={{ width: SCREEN_WIDTH - 20, marginTop: 0, justifyContent: 'center', alignSelf:
'center' }}>
<View style={{ flexDirection:'row' }}>
<Avatar
size="small"
rounded
source={card.photo[i]}
/>
<View style={{ flex:2, flexDirection:'row', justifyContent:'flex-end' }}>
<Avatar
rounded
icon={{ name:'heart-multiple-outline', type:'material-community'}}
overlayContainerStyle={{backgroundColor: '#ff4284',marginLeft:5}}
reverse
size='small'/>
<Avatar
reverse
rounded
icon={{ name:'comment-processing-outline', type:'material-community' }}
overlayContainerStyle={{backgroundColor: '#dbdbdb',marginLeft:5}}
size='small'/>
</View>
</View>
<View style={{ flexDirection:'row' }}>
<Text style={{fontFamily: 'MontserratB', color:'#bf00b9', marginTop:10}}>{username}</Text>
<Text style={{fontFamily:'Montserrat', marginTop:10}}>{card.caption[i]}</Text>
</View>
<Text style={{marginTop:4, color:'#878787'}}>{card.comments[i]}</Text>
</Card>
<Button style={{marginTop:0, borderBottomRightRadius: 20, borderBottomLeftRadius: 20, borderTopLeftRadius: 0, borderTopRightRadius: 0, width: SCREEN_WIDTH - 20, alignSelf: 'center', justifyContent: 'center'}} title="Close" onPress={this.toggleModal} />
</Modal>
</View>
);
return <React.Fragment />;
});
})
}
everything works perfectly except that no matter which Card is touched a Modal is opened presenting the last objects in the array. So no matter which of the three cards are pressed, a Modal will always open with the information regarding David
Modified snack version of your sample:
https://snack.expo.io/H1yHPQQdr

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.

Like functionality like Facebook react native

I am using a list of image.Below every image,there is a like button. When i click on the Like button, likes should be increases which is working fine. But it should work on the image I click. Currently it is increasing like count of all the images.I am new to react native.Any help would be appreciated.
Here, this is my code
export default class Art extends Component {
constructor(props) {
super(props)
this.state = {
value: null,
liked:false
}
}
_increaseValue(){
console.log(this.state.liked)
if (this.state.liked==false)
{
this.setState({liked: !this.state.liked})
newvalue =this.state.value +1;
this.setState({value:newvalue})
}
else
{
this.setState({liked: !this.state.liked})
newvalue =this.state.value -1;
this.setState({value:newvalue}
}
}
render() {
const datas = [
{
img: images[0]
},
{
img: images[1]
},
{
img: images[2]
},
{
img: images[3]
},
];
const { navigate } = this.props.navigation;
// eslint-disable-line
return (
<Content padder style={{ marginTop: 0, backgroundColor: '#3b5998' }}>
<List
style={{ marginLeft: -19, marginRight: -19 }}
dataArray={datas}
renderRow={data =>
<ListItem >
<Card
wrapperStyle={{ marginLeft: -10, marginTop: -10, marginRight: -10, }} containerStyle={{ marginLeft: 2, marginTop: -5, }}>
<TouchableOpacity activeOpacity={.5} onPress={() => navigate('ImageDisplay',{item:data})}>
<Image source={{ uri: data.img }} style={[styles.imageContainer, styles.image]}/>
</TouchableOpacity>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around', marginTop: 20 }}>
<View style={{flexDirection:'row'}}>
<TouchableOpacity activeOpacity={.5} onPress={() => {this._increaseValue()}}>
<View>
{this.state.liked ? <Icon active name="favorite" style={styles.iconCountContainer} color='red' size={14}/>
: <Icon name="favorite" style={styles.iconCountContainer} size={14}/>}
</View></TouchableOpacity>
<Text style={{color:'#000000',fontSize:15, marginLeft:12, marginTop:5}}>{this.state.value} Likes </Text>
</View>
<View style={styles.iconCountContainer}>
<Icon active name="share" size={14} style={styles.share} onPress={() => Share.open(shareOptions).catch((err) => { err && console.log(err); })} />
</View>
</View>
</Card>
</ListItem>
}
/>
</Content>
);
}
}
You need to convert your Cards into separate components or store the like counts separately in state. You can approach this problem several ways. I'll give you an example of how you can achieve this behavior and you can implement it the way you like.
Example
export default class CutomListItem extends React.Component {
constructor(props) {
this.state = {
likes: 0
};
}
_increaseValue = () => {
this.setState((prevState) => {
return {
likes: prevState.likes++
};
});
}
render() {
const { data, navigate, share } = this.props; // send data with props
<ListItem >
<Card
wrapperStyle={{ marginLeft: -10, marginTop: -10, marginRight: -10, }} containerStyle={{ marginLeft: 2, marginTop: -5, }}>
<TouchableOpacity activeOpacity={.5} onPress={() => navigate('ImageDisplay',{item:data})}>
<Image source={{ uri: data.img }} style={[styles.imageContainer, styles.image]}/>
</TouchableOpacity>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-around', marginTop: 20 }}>
<View style={{flexDirection:'row'}}>
<TouchableOpacity activeOpacity={.5} onPress={() => {this._increaseValue()}}>
<View>
{this.state.liked ? <Icon active name="favorite" style={styles.iconCountContainer} color='red' size={14}/>
: <Icon name="favorite" style={styles.iconCountContainer} size={14}/>}
</View></TouchableOpacity>
<Text style={{color:'#000000',fontSize:15, marginLeft:12, marginTop:5}}>{this.state.likes} Likes </Text>
</View>
<View style={styles.iconCountContainer}>
<Icon active name="share" size={14} style={styles.share} onPress={() => Share.open(shareOptions).catch((err) => { err && console.log(err); })} />
</View>
</View>
</Card>
</ListItem>
}
}
return (
<Content padder style={{ marginTop: 0, backgroundColor: '#3b5998' }}>
<List
style={{ marginLeft: -19, marginRight: -19 }}
dataArray={datas}
renderRow={data => (<CutomListItem data={data} navigate={navigate} share={Share} />}
/>
</Content>
);
}