I am generating a list with List item in React native, and for a specific reason I want the first item to navigate to a different screen and all other item to a different screen.
I am putting the condition with ternary operator for the same but there is no success
<View style={{flex: 1, backgroundColor: '#fff'}}>
<List containerStyle={{ borderTopWidth: 0, borderBottomWidth: 0 }}>
<FlatList
data={this.state.schools}
renderItem={({ item }) => ({
item.school_name == "all" ?
<ListItem
title={item.school_name}
onPress={()=>this.props.navigation.navigate('DepartmentSchools', {
school_name: item.school_name,
school_id : item.school_id
})}
/> :
<ListItem
title={item.school_name}
onPress={()=>this.props.navigation.navigate('DepartmentIndividual', {
school_name: item.school_name,
school_id : item.school_id
})}
/>
})}
keyExtractor={item => item.school_name}
ItemSeparatorComponent={this.renderSeparator}
/>
</List>
</View>
Please help in resolve this or you can point out my mistake.
Thanks in advance.
Move the condition to the onPress handler like this :
<FlatList
data={this.state.schools}
renderItem={({ item }) => (
<ListItem
title={item.school_name}
onPress= {
()=>{
let destination = item.school_name === "all" ? "DepartmentSchools" : "DepartmentIndividual";
this.props.navigation.navigate(destination, {
school_name: item.school_name,
school_id : item.school_id
});
}
}
/>
)}
keyExtractor={item => item.school_name}
ItemSeparatorComponent={this.renderSeparator}
/>
Related
My goal is for this entire block to be scrollable.
I tried all kinds of ways to achieve the goal but without success.
I tried with ListHeaderComponent and moved the entire top view to it and it didn't work.
And I also tried <FlatList nestedScrollEnabled />
And it didn't work either.
What is the correct way to reach the scroll?
I come from here :
const renderAccordians = () => {
const items: JSX.Element[] = [];
areaData.forEach(item => {
items.push(<Accordian item={item} key={item.title} />);
});
return items;
};
To here :
return (
<View>
<View style={styles.row}>
<TouchableOpacity onPress={() => onClickFather()}>
<MaterialIcons size={24} name={data.checked ? 'check-box' : 'check-box-outline-blank'} color={'black'} />
</TouchableOpacity>
<Text style={[styles.title]}>{data.title}</Text>
<TouchableOpacity style={styles.row} onPress={() => toggleExpand()}>
<MaterialIcons name={expanded ? 'arrow-drop-up' : 'arrow-drop-down'} size={30} color={'black'} />
</TouchableOpacity>
</View>
<View style={styles.parentHr} />
{expanded && (
<FlatList
data={data.data}
numColumns={1}
scrollEnabled={false}
renderItem={({ item, index }) => (
<View>
<TouchableOpacity style={[styles.childRow, styles.button]} onPress={() => onClick(index)}>
<MaterialIcons
size={24}
name={item.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
<Text style={[styles.itemInActive]}>{item.key}</Text>
</TouchableOpacity>
<View style={styles.childHr} />
</View>
)}
/>
)}
</View>
);
Since your FlatList will be part of an Accordion component, you "can't" embed the ExpandButton inside the Flatlist > ListHeaderComponent ... cause It'll simply hide the whole FlatList along with it's Header when you collapse your accorddion...
keyExtractor is also missing in your FlatList .. I added index as a key here which is not recommended BTW, you better use a unique field in your listItem like id...
return (
<View style={{ flex: 1}}> // <<--- Look here
<View style={styles.row}>
<TouchableOpacity onPress={() => onClickFather()}>
<MaterialIcons
size={24}
name={data.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
</TouchableOpacity>
<Text style={[styles.title]}>{data.title}</Text>
<TouchableOpacity style={styles.row} onPress={() => toggleExpand()}>
<MaterialIcons
name={expanded ? 'arrow-drop-up' : 'arrow-drop-down'}
size={30}
color={'black'}
/>
</TouchableOpacity>
</View>
<View style={styles.parentHr} />
{expanded && (
<FlatList
data={data.data}
numColumns={1}
scrollEnabled={true} // <<--- Look here
keyExtractor={(_, index) => index.toString()} // <<=== Look here
contentContainerStyle={{flexGrow: 1}} // <<--- Look here
renderItem={({ item, index }) => (
<View>
<TouchableOpacity
style={[styles.childRow, styles.button]}
onPress={() => onClick(index)}
>
<MaterialIcons
size={24}
name={item.checked ? 'check-box' : 'check-box-outline-blank'}
color={'black'}
/>
<Text style={[styles.itemInActive]}>{item.key}</Text>
</TouchableOpacity>
<View style={styles.childHr} />
</View>
)}
/>
)}
</View>
);
If it does not work, I think you should create a component and use map datalist to render all the items and putting them into the ScrollView tag.
<ScrollView
style={styles.messageContain}
ref={ref => {
this.scrollView = ref;
}}
{data.data.map((item, index) => {
return <YourComponent key={index} data={item} />;
})}
</ScrollView>
I have the below code to loop through an array.
export default function App() {
const [x, setX] = useState([
{name:'a'},{name:'b'}
]);
return (
<View >
<FlatList
data={x}
renderItem={(item) => {
return <Text>{item.name}</Text>;
}}
/>
</View>
);
The above code gives below error
Warning: Failed child context type: Invalid child context `virtualizedCell.cellKey` of type `number` supplied to `CellRenderer`, expected `string`.
When I change
<FlatList
data={x}
renderItem={(item) => {
return <Text>{item.name}</Text>;
}}
/>
To
<FlatList
data={x}
renderItem={({item}) => {
return <Text>{item.name}</Text>;
}}
/>
The code is correct now and it works, see I changed (item) to ({item}) added curly braces .
Why is so ?
As you can see link document https://reactnative.dev/docs/flatlist.html
renderItem
renderItem({ item, index, separators });
item: (Object): The item from data being rendered.
index (number): The index corresponding to this item in the data array.
separators (Object)
highlight (Function)
unhighlight (Function)
updateProps (Function)
select (enum('leading', 'trailing'))
newProps (Object)
Example usage:
<FlatList
ItemSeparatorComponent={
Platform.OS !== 'android' &&
(({ highlighted }) => (
<View
style={[
style.separator,
highlighted && { marginLeft: 0 }
]}
/>
))
}
data={[{ title: 'Title Text', key: 'item1' }]}
renderItem={({ item, index, separators }) => (
<TouchableHighlight
key={item.key}
onPress={() => this._onPress(item)}
onShowUnderlay={separators.highlight}
onHideUnderlay={separators.unhighlight}>
<View style={{ backgroundColor: 'white' }}>
<Text>{item.title}</Text>
</View>
</TouchableHighlight>
)}
/>
you should use the key prop flour. try again with the code below
<FlatList
data={x}
renderItem={({ item, index }) => (
<Text key={index}>{item.name}</Text>
)}
keyExtractor={(item, index) => index.toString()}
/>
Because the FlatList returns item object in which their is your items or array to be render!
its like
{
items: {
{name:'a'},
{name:'b'}
}
}
so we have to go to item first by destructuring by {item} and then access the inner objects.
Hope it will make understanding !
Kind of surprised at the lack of information I can find about this question, feel like its something that you be done pretty often? I know with a standard dropdown it's pretty easy, you set up a hook that controls state with a boolean, when that boolean is true, you show the dropdown, when it's false, you show the closed version.
The Issue that I discovered when trying to do this with each render item is that the hook state control needs to be in the global context, because of this whenever you click on Flatlist item, all of the items open because they are all using the same state control. How would you make it so that each rendered item has its own dropdown state when you can't set a state hook inside each render item?
Here's my code to give you a better idea of what I'm talking about, be sure to read the comments:
<FlatList
contentContainerStyle={{ alignItems: 'center', marginVertical: 10, minHeight: 200 }}
data={notes}
keyExtractor={(item, index) => item.key}
ListFooterComponent={() => <AddNoteFooter onPress={addSpecificNote} />}
renderItem={({ item }) => {
//would need something similar to a hook right here,
// to manage the state of each item individually
//change "isOpen" state when button is pressed
return (
<View>
{!isOpen &&
<TouchableOpacity onPress={null} style={styles.flastliststyle}>
<Text style={styles.flastlistItemText}>{item.note}</Text>
</TouchableOpacity>
}
{isOpen &&
<TouchableOpacity>
/* extended dropdown code */
</TouchableOpacity>
}
</View>)
}
Looking to do something similar to this video but where each item is a flatlist item (also using hooks):
https://www.youtube.com/watch?v=awEP-pM0nYw&t=134s
Thank you!
SOLUTION:
flatlist:
<FlatList
contentContainerStyle={{ alignItems: 'center', marginVertical: 10, minHeight: 200 }}
data={notes}
keyExtractor={(item, index) => item.key}
ListFooterComponent={() => <AddNoteFooter onPress={addSpecificNote} />}
renderItem={({ item }) => {
return (
<NoteItem noteitem={item} />
)
}}
/>
then the component rendered for each item:
const NoteItem = (props) => {
const [isOpen, updateDrop] = useState(false)
return (
<View>
{!isOpen &&
<TouchableOpacity onPress={() => updateDrop(prev => !prev)} style={styles.flastliststyle}>
<Text style={styles.flastlistItemText}>{props.noteitem.note}</Text>
</TouchableOpacity>
}
{isOpen &&
<TouchableOpacity onPress={() => updateDrop(prev => !prev)} style={styles.flastliststyle}>
<Text style={styles.flastlistItemText}>pressed</Text>
</TouchableOpacity>
}
</View>
)
}
When a user selects an item from flat list, I want that selected item set to the input field.
I am using a flat List view for display records data in Flat list coming from the database
Please anyone help me,to what i can do,tell me i am doing wrong
searchText(e) {
this.setState({ searchCustomer: text, display_List: 'flex' })
let text = e.toLowerCase()
let trucks = C_name
}
renderRow = (item) => {
return (
<TouchableOpacity>
<ListItem
hideChevron={true}
// item={item}
title={`${item} `}
onPressItem={this.onPressAction(item)}
/>
</TouchableOpacity>
);
}
onPressAction = (rowItem) => {
console.log('ListItem was selected');
// console.log(`User${rowItem}`);
console.log(`User${rowItem.value}`);
this.setState({
selectedItem: rowItem.value
});
// console.log(`User${this.state.selectedItem}`);
}
render() {
return (
<FormLabel>Search Customer</FormLabel>
<FormInput
inputStyle={styles.SearchCustomer}
placeholder="Search Customer"
value={this.state.selectedItem}
onChangeText={(text) => this.searchText(text)} />
<List
containerStyle={{
display: this.state.display_List,
borderTopWidth: 0, borderBottomWidth: 0,
}}>
<FlatList
ItemSeparatorComponent={this.renderSeparator}
data={C_name}
rightIcon='hideChevron'
extraData={this.state}
keyExtractor={(item) => item}
renderItem={({ item }) => (
this.renderRow(item)
)} />
</List>
);
}
}
renderRow = (item) => {
return (
<TouchableOpacity>
<ListItem
hideChevron={true}
id={item.CCODE}
onPress={() => this.onPressAction(item.CNAME)}
title={`${item.CNAME} `}
/>
</TouchableOpacity>
);
};
onPressAction = (name) => {
this.setState( {
searchCustomer:name,display_List: 'none'
});
};
render() {
return (
<ScrollView>
<View style={styles.container}>
<FormLabel>Search Customer</FormLabel>
<FormInput
inputStyle={styles.SearchCustomer}
placeholder="Search Customer"
onChangeText={(text) => {this.searchText(text)}}
value={this.state.searchCustomer}
/>
<List
containerStyle={{
display: this.state.display_List,
borderTopWidth: 0, borderBottomWidth: 0,
}}>
<FlatList
ItemSeparatorComponent={this.renderSeparator}
data={C_name}
rightIcon='hideChevron'
extraData={this.state}
keyExtractor={(item) => item.CCODE}
renderItem={({ item }) => (
this.renderRow(item)
)} />
</List>
</View>
</ScrollView>
I am doing like that and it works fine
i'm new in react native and i need your help
i want to give border-bottom to pressed item of horizontal flatlist and border-bottom of Previous item disappear,
now i can give border to new pressed item but i cant remove previous item border
how can i achive this?
enter image description here
these are my Category_style code
state = {
isModalVisible: false,
Index : 0
}
_toggleModal = (index) => {
this.setState({isModalVisible: !this.state.isModalVisible});
this.setState({Index : index});
}
renderProduct(item) {
return <Sub_Categories_FlatList_style name={item.title} icon={item.icon}/>
}
renderSeparator = () => (
<View
style={{
backgroundColor: '#d2d2d2',
height: 0.5,
}}
/>
)
render() {
const {title, index} = this.props;
return (
<View style={pStyles.container}>
<TouchableHighlight onPress={() => this._toggleModal(index)}
style={(index === this.state.Index) ? pStyles.border_bottom : pStyles.no_border_bottom}>
<Text style={pStyles.title}>{title}</Text>
</TouchableHighlight>
<Modal isVisible={this.state.isModalVisible} animationType={'slide'}>
<TouchableOpacity onPress={() => this._toggleModal(index)} style={pStyles.T_opacity}
activeOpacity={.7}>
<Image source={require('./../pictures/x_icon.png')}
style={pStyles.close_image}/>
</TouchableOpacity>
<View style={pStyles.in_modal_view}>
<Text style={pStyles.modal_header_text}>{title}</Text>
<FlatList
data={this.props.subCategory}
renderItem={({item}) => this.renderProduct(item)}
ItemSeparatorComponent={this.renderSeparator}
keyExtractor={(item, index) => index}/>
</View>
</Modal>
</View>
and these are my Category code
static navigationOptions = {
headerStyle: {
backgroundColor: '#4caf50'
},
headerTitle: <Text style={Category_in_style.headerTitleStyle}>Category</Text>
}
renderCategory(item, index) {
return <Category_style title={item.title} index={index} subCategory={item.sub_category}/>
}
renderProduct(item) {
return <Product_style image={item.imageUrl} title={item.title} price={item.price}/>
}
render() {
return (
<View style={{backgroundColor: 'white'}}>
<FlatList style={styles.first_flat}
horizontal
data={this.state.main_categories}
renderItem={({item, index})=> this.renderCategory(item, index)}
keyExtractor={(item, index) => index}/>
<PTRView style={{backgroundColor: '#f1f1f1'}}>
<FlatList style={[{marginTop: 10}, {marginBottom: 50}]}
data={this.state.articles}
renderItem={({item}) => this.renderProduct(item)}
keyExtractor={(item, index) => index}
numColumns={2}/>
</PTRView>
</View>
There may be multiple ways of doing this but I prefer having the parent decide which component is clicked.
So what I suggest is in your renderProduct the item object also has an index which you can pass to your Sub_Categories_FlatList_style and also pass a function to it which basically updates a variable whenever the item is clicked.
Then when you render the list item simply check if it's index matches the currently selected index and then style it accordingly.
Sorry if this seems a bit vague but I'm eyeballing this since I'm at work but I'll be more than happy to answer any follow ups.