Separator style for header and body in FlatList - react-native

Currently, I'm having a problem with FlatList.
I have a component to render a list book.
By design, the header's width is the width of the screen and the body will be padding left and right 10px.
So I used contentContainerStyle={{paddingHorizontal: 10}}.
But The result is that the header and body are 10px padding left and right.
Please suggest a way to resolve it. Sorry for my bad English!!
Update: I'm so sorry for not describing my problem thoroughly.
In main.tsx
...
public render() {
return (
<FlatList
key...
data={..}
renderItem={this.renderItems}
ListHeaderComponent={this.renderHeader}
contentContainerStyle={styles.contentStyle}
/>
);
}
private renderHeader = () => {
return (
<View style={style.header}
//TODO something ...
</View>
);
}
private renderItems: ListRenderItem<IBook> = ({ item: {bookId} }) => bookId ?
(
<BookGridCell
title={...}
image={...}
//TODO more..
/>
) : <View style={styles.emptyBox} />
}
At renderItems, I called a component BookGridCell. In this component, the design of a book is set up. So if I directly add style inside renderItems, each book will have a left and right margin of 10px, not the entire body.
When use contentContainerStyle
with contenContainerStyle
When directly add style inside renderItems
with not use contentContainerStyle

Give a style to your body.
style={styles.bodyContainer}
and then inside StyleSheet add property.
const styles = StyleSheet.create({
bodyContainer: {
paddingHorizontal: 10
},
This is the correct way or
you can directly add padding inside your View.
style={{ paddingHorizontal: 10 }}

Related

Can't overwrite external stylesheet property with inline style in React Native

I have a custom TextInput component that takes in two stylesheets and appends any inline styles afterwards and passes those to the TextInput style property:
class WSTextInput extends React.Component<TextInputProps> {
render() {
return (
<TextInput
style={[styles.defaultText, styles.defaultTextInput, this.props.style] as StyleProp<TextStyle>}
{...this.props}
/>
);
}
}
These are the stylesheets it uses:
defaultText: {
fontSize: 24,
fontFamily: 'cardenio-modern'
},
defaultTextInput: {
flex: 1,
alignSelf: 'stretch',
textAlign: 'center',
backgroundColor: '#fafafa',
borderBottomWidth: 1,
margin: 10
}
The code works fine so as long as this.props.style does not attempt to overwrite any of the existing properties in defaultText or defaultTextInput.
When I do try to do so, e.g. with this element (note that styles.defaultTextInput's borderBottomWidth and backgroundColor are overwritten):
<WSTextInput style={{ borderBottomWidth: 0, backgroundColor: 'transparent' }}
editable={false}
value={this.state.total.toString()}
/>
Then this is the result:
The top right element is a WSTextInput rendering correctly without inline overrides; the bottom right element is a WSTextInput with the above inline overrides rendering incorrectly.
When I open reactnative-tools and inspect the element tree, I see this for the top right element:
And this for the bottom right element:
So it seems that for the bottom right element, the inline style survives, but both stylesheets are lost.
I have tried different ways of coalescing the properties in WSTextInput.render, e.g. using Object.assign or the spread operator, but the result is the same. Any insights would be appreciated.
I'm still not exactly clear on what the desired outcome is because it's not great to not allow the font size and some others to not be overridden. But, I think this is just as simple as moving the props to the first arg so they are overridden by yours.
render() {
const {style, ...theRest} = this.props;
return (
<TextInput
{...this.props}
style={[styles.defaultText, styles.defaultTextInput] as StyleProp<TextStyle>}
/>
);
}
For more control try removing the style from the props and passing it where desired in the style props so font is overridden but other stuff isn't.
render() {
const {style, ...theRest} = this.props;
return (
<TextInput
style={[styles.defaultText, style, styles.defaultTextInput] as StyleProp<TextStyle>}
{...theRest}
/>
);
}
Finally, you can explicitly remove the ones you don't want overridden thru deconstruction and pass thru anything else.
const {style, ...theRest} = this.props;
const {backgroundColor, borderBottomWidth, ...theRestOfStyle} = style;
Then use it in your style:
<TextInput
style={[styles.defaultText, styles.defaultTextInput, theRestOfStyle] as StyleProp<TextStyle>}
{...theRest}
/>

How can I display 30 pages of text in a (scrolling) screen

I want to display 30 pages of text on a screen. I've tried ScrollView and FlatList but I get a white screen. Only when I try with ScrollView to display only 2 pages, works fine.
I do not want to use a WebView, because I would like to have all data in the app (no internet connection needed).
Here is what I've already tried:
With FlatList:
I have a text.js as a model, which I use to create a Text Object in an array, which I then use as data for the FlatList. For the renderItem function (of FlatList) I use a TextItem to display the text.
text.js
function Text(info) {
this.id = info.id;
this.text = info.text;
}
export default Text;
LongTextModule.js
import Text from '../../models/text';
export const LONGTEXT = [
new Text({
id:'text_1',
text:`.....longtext....`
})
]
TextItem.js
const TextItem = (props) => {
return (
<View style={styles.screen} >
<Text style={styles.textStyle}>{props.longText}</Text>
</View >
);
};
const styles = StyleSheet.create({
screen: {
flex: 1,
},
textStyle: {
justifyContent: 'flex-start',
alignItems: 'flex-start',
fontFamily: 'GFSNeohellenic-Regular',
fontSize: 20,
padding: 10,
}
});
TextDetailScreen.js
const TextDetailScreen = (props) => {
const renderText = data => {
return <TextItem longText={data.item.text} />
}
return <FlatList
data={LONGTEXT}
keyExtractor={(item, index) => item.id}
renderItem={renderText}
/>
};
I think it's needless to show the code with ScrollView, since ScrollView is only for a small list.
I even tried to render the longText like this in the screen.
Without the ScrollView I get the first portion, but with ScrollView a white screen.
const TextDetailScreen = (props) => {
return (
<ScrollView>
<Text> ...longText...</Text>
</ScrollView>
);
};
I'm sure there is a way to display a lot of pages of text on a screen?
But how?
Thank you :)
It seems not to be an unknown Issue, I've also read from time to time about this issue.
But not to use Webview, because you wan't to have all Data in your app - don't have to be an Argument against Webview. With WebView, you also can display Data from your App-Storage.
Example:
<WebView style={styles.myStyle} source={{html: `<p style="font-size:48px">${longtext}</p>`}} />

What is the best practice to align a header a button, text and right component in UI using react-native

I need to align the Back button and Text and Right element in my header section.
I am using react-native-elements component to align but the styles Which I gave not worked for all text. If the text is small it not working as expected.Also If I try line spacing for the text LIST it not shows space in it. Refer the expo for sample code(here I not added line spacing) and refer the attachment.
https://snack.expo.io/#niph/grounded-watermelon
My question what is the best practice to achieve this. I have added marginLeft values as negative.
You have put your title name under the left button in the header. This eliminates the need to use centerComponent.
And you have to use outerContainerStyles to change the height of the header. Then, adjust the area using flex values and use alignSelf to reposition only text.
Usage If you want to experience this, look at my example.
export default class App extends React.Component {
render() {
return ( <Header
outerContainerStyles={{paddingTop: 0, height:130}}
backgroundColor='green'
leftComponent = {
<View style={{flexDirection:"row",flex:1,marginTop:20}}>
<TouchableOpacity activeOpacity = { .5 }>
<Entypo name = {'chevron-thin-left'} size ={30} style = {{ color:'white'}}></Entypo>
</TouchableOpacity>
<Text style={{fontSize:30, color:'white',alignSelf:"flex-end"}}>NAMES</Text>
</View>
}
// centerComponent = {<Text style={{fontSize:30, color:'white', flexDirection:'row'}}>NAMES</Text>}
rightComponent = {<TouchableOpacity activeOpacity = { .5 } style={{flex:1,marginTop:20}}>
<Text style={{ fontSize:14, color:'white',textDecorationLine:'underline'}}>LIST</Text>
</TouchableOpacity>}
/>
);
}
}
Enabled screen

View config not found for name "" react native

when I'm trying to insert Image into View I get this error
View config not found for name ""
renderCategory = (category)=>{
const { Id, Image, Name } = category.item
const { button, image_category, text_category} = style;
return(
<TouchableOpacity style={style.button} onPress={()=>{console.log(Id)}}>
<View style={{flex:1}}>
//here the problem
<Image style={image_category} source={{uri:'https://picsum.photos/150/150'}} /> // when I remove it, it works fine.
<Text>{Name}</Text>
</View>
</TouchableOpacity>
)
}
render() {
const { container } = style;
return (
<View style={container}>
<FlatList style={{margin:5}}
data={this.state.second_categories}
numColumns={3}
keyExtractor={(item, index) => item.id }
renderItem={this.renderCategory}
/>
</View>
)
}
I looked in other post in stackoverflow but nothing solved my issue.
my styles
image_category:{
width: calcSize(width/4),
height: calcSize(width/4)
},
This issue is due to overwriting of the reserved-word Image.
const { Id, Image, Name } = category.item
The Image string being used in the below code is from category.item, and not the one from {Image} from 'react-native'
<Image style={image_category} source={{uri:'https://picsum.photos/150/150'}} />
Therefore you need to replace the Image object in your category.item object to something else, that is not a react-native reserved word to avoid conflicts.
OR
You may make a stateless component for the image and use it
TLDR
Replace the Image object in category.name to something else as it conflicts with react-native's tag Image or make a separate component for the image
I can't tell what you have in image_category but it must have width and height https://facebook.github.io/react-native/docs/image.html

React Native - FlatList Not Rendering

(Note: I'm using Expo for this app)
I'm attempting to render a FlatList that displays a list of printers. Here's the code:
<FlatList
data={printers}
keyExtractor={printer => printer.id}
renderItem={({ item }) => {
return (
<Printer
printerTitle={item.name}
selected={item.selected}
last={item === last(printers)}
/>
);
}}
/>
Here's the code for the <Printer /> component:
const Printer = props => {
const { last, printerTitle, selected } = props;
return (
<View style={[styles.container, last ? styles.lastContainer : null]}>
<View style={styles.innerContainer}>
<View style={styles.leftContainter}>
{selected ? (
<Image source={selected ? Images.checkedCircle : null} />
) : null}
</View>
<View style={styles.printerDetails}>
<Text style={styles.printerTitle}>{printerTitle}</Text>
</View>
</View>
</View>
);
};
...
export default Printer;
I can't seem to get the <Printer /> component to render. I have tried including a similar custom component (that has worked in a FlatList in another part of the app) in the renderItem prop, and it doesn't work either.
However, when I replace the <Printer /> component with <Text>{item.name}</Text> component, the printer name renders like I would expect it to.
Has anyone run into this issue before, or does anyone have a solution?
In my case, where I'm rendering a custom component for each item in the list, it wasn't rendering because I accidentally had {} surrounding the return part of the renderItem prop instead of ().
Changing:
<FlatList
data={array}
renderItem={({item, index}) => { <CustomItemComponent /> }}
/>
to this:
<FlatList
data={array}
renderItem={({item, index}) => ( <CustomItemComponent /> )}
/>
Solved my issues.
I suspect there are two issues at hand: one is that your FlatList is not filling the screen (namely its parent view) and the other is that your Printer component is not being sized correctly.
For the first issue, put a style with { flex: 1 } on your FlatList. This way it will fill its parent view.
For the second issue, try adding { borderColor: 'red', borderWidth: 1 } to your Printer components, just so that you can more easily see where they're being rendered. If they seem like they have no width, make sure you haven't overridden alignSelf on the Printer component's root view. If they seem like they have no height, add height: 100 temporarily just so you can see what the contents of the Printer components look like.
Within your Printer component, make sure to specify the width and height of your image on the Image component like { width: 40, height: 30 } or whatever the dimensions of your image is in logical pixels.
I have same problem.
Resolve with adding width to FlatList
render() {
const dimensions = Dimensions.get('window');
const screenWidth = dimensions.width;
return(
<FlatList
style={{
flex: 1,
width: screenWidth,
}}
... some code here
/>
)
}
You can't use the keyExtractor in this way, make this function like below. It might solve your problem.
_keyExtractor = (item, index) => index;
If you update your question with you printer component code we can help you better.
In my case I accidentally made it a pair tag: <FlatList></FlatList>, which for some reason breaks rendering of list items.
in my case Container was not having width of 100%:
const Container = styled.View`
border: 1px solid #ececec;
margin-top: 43px;
padding-top: 36px
padding-bottom: 112px;
width: 100%;
`;
const StyledFlatList = styled(
FlatList as new () => FlatList<SimilarRewards_viewer['merchants']['edges'][0]>
)`
width: 100%;
height: 150px;
flex: 1;
padding-left: 15px;
padding-right: 15px;
`;