changing text in Flatlist for each item - react-native

Hey guys I would like to know how to change text in each row of a Flatlist.
I want to be able to toggle between follow and unfollow.
Here's my code example :=>
this.state = {
FlatListItems : [
{"key": "MARIA", "image":require("./assets/image/maria.jpg")},
{"key": "MARTA", "image":require("./assets/image/marta.jpg")},
{"key": "MARTIN", "image":require("./assets/image/martin.jpg") },
{"key": "OLIVIA", "image":require("./assets/image/olivia.jpg") },
],
checked:true,
}'
And here's the checked function
checked=()=>{
if(checked==true)
{
this.checked.setState(true)
}
else{
this.checked.setState(False)
}
}
And here's the render function
<FlatList
contentContainerStyle={{
flexDirection: 'row',alignItems:'center',paddingLeft:10,borderTopRightRadius:10,borderTopLeftRadius:10,
flexWrap: 'wrap',}}
data={ this.state.FlatListItems }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item,key}) =><View style={{padding:5,borderTopRightRadius:10,borderTopLeftRadius:10,}}>
<ImageBackground source={item.image}
style={{height:230,width:185,borderTopRightRadius:10,borderTopLeftRadius:10}}
blurRadius={ Platform.OS == 'ios' ? 10 : 6 } >
<View style={{alignItems:'center',padding:20,backgroundColor:'rgba(0,0,12, 0.4)'}}>
<View style={{alignItems:'center',padding:20}}>
<Image source={item.image} style={{width: 90, height: 90, borderRadius: 60}}/>
</View>
<View style={{alignItems:'center',paddingTop:10}}>
<Text style={{fontSize:18,fontFamily:'CRC55',color:'white'}}>{item.key}</Text>
<Text style={{fontSize:22,fontFamily:'CRC55',color:'white',paddingTop:10}}>{item.key}</Text>
<View style={{backgroundColor:'white',width:185,height:10}}>
</View>
</View>
</View>
</ImageBackground>
{
!this.state.checked? <TouchableOpacity onpress={this.checked}
><Text style={{fontSize:20,alignItems:'center'}}>FOLLOWING</Text></TouchableOpacity>: <TouchableOpacity onpress={()=>{this.setState({checked:key})}}><Text style={{fontSize:20,alignItems:'center'}}>FOLLOW</Text></TouchableOpacity>
}
</View>
}
/>
My question is how can I toggle between follow and unfollow for each item in the Flatlist.

You can use directly this example. I have just used some code from offical docs. You keep each list item state separately. You can adjust this code easily for your needs
import React, { Component } from 'react'
import { Text, View, FlatList, TouchableOpacity } from 'react-native'
const data = [
{ "key": "MARIA", "title": "image MARIA", "id": 1 },
{ "key": "MARTIN", "title": "image MARTIN", "id": 2 },
{ "key": "OLIVIA", "title": "image OLIVIA", "id": 3 },
];
class MyListItem extends React.PureComponent {
state = {
selected: true
}
_onPress = () => {
this.setState({
selected: !this.state.selected
})
};
render() {
const text = this.state.selected ? "follow" : "unfollow";
return (
<TouchableOpacity onPress={this._onPress}>
<View>
<Text >
{this.props.title + " " + text}
</Text>
</View>
</TouchableOpacity>
);
}
}
export default class MultiSelectList extends React.PureComponent {
_keyExtractor = (item, index) => item.id;
_renderItem = ({ item }) => (
<MyListItem
id={item.id}
title={item.title}
/>
);
render() {
return (
<FlatList
data={data}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
/>
);
}
}

Related

How to select multiple checkbox and get the value of selected checkbox in react native?

I have a checkbox inside Flatlist, but I don't know how to get index of the checkbox and set checkbox from Flatlist. Also, I want to get data selected checkbox from flatlist. So the user will get selected checkbox either will be accepted or rejected base on button clicked.
This is my array :
const DATA = [
{
"start": "2022-01-01 10:35:08",
"id": "298269",
"tanggal": "01-01-2022",
"hari": "Saturday",
"waktu": "10:35:08",
"keterangan_plan": null,
"outlet": "26506",
"nama": "RS Ibu dan Anak Propinsi NAD",
"nama_customer": "DR. IQBAL",
"customer": "39359",
"prod1": "ADSV WOUND STRIP ",
"prod2": "",
"prod3": "",
"prod4": "",
"keterangan": "tes",
"title": "",
"end": "2022-01-01",
"verifikasi": "Y",
"status": null,
"job": "Dokter",
"lokasi": "-6.992191,107.590668",
"verifikasi_plan": null
},
{
"start": "2022-01-01 10:42:57",
"id": "298270",
"tanggal": "01-01-2022",
"hari": "Saturday",
"waktu": "10:42:57",
"keterangan_plan": null,
"outlet": "26506",
"nama": "RS Ibu dan Anak Propinsi NAD",
"nama_customer": "RONI",
"customer": "39362",
"prod1": "COAT ",
"prod2": "",
"prod3": "COAT ",
"prod4": "",
"keterangan": "cek",
"title": "",
"end": "2022-01-01",
"verifikasi": "Y",
"status": null,
"job": "Pharmacist",
"lokasi": "-6.992191,107.590668",
"verifikasi_plan": null
},
];
this is my code for rendering the flatlist
const SubmitVerKunjungan = () => {
const [datas, setData] = useState(DATA);
const [toggleCheckBox, setToggleCheckBox] = useState(false);
const renderFlatlist = (renderData) =>{
return(
<FlatList
data={renderData}
renderItem={({ item }) => (
<View style={style.viewItem}>
<View style={style.firstItem}>
<Text style={style.tanggal}>{item.hari}, {item.tanggal}</Text>
<Text style={style.lokasi}></Text>
<Checkbox
disabled={false}
value={toggleCheckBox}
onValueChange={(newValue) => setToggleCheckBox(newValue)}
/>
</View>
<View style={style.secondItem}>
<View style={style.secondItemSub}>
<Image
style={style.iconOffice}
source={require('../../assets/office.png')}/>
<View style={style.subSecondItem}>
<Text style={style.subSecondItemTitle}>{item.nama}</Text>
<Text style={style.subSecondItemTitle}>{item.nama_customer} ({item.job})</Text>
</View>
</View>
<Image
style={style.iconMaps}
source={require('../../assets/maps.png')}/>
</View>
<Text style={style.keteranganItem}>Keterangan : {item.keterangan}</Text>
<View style={style.thirdItem}>
<Text style={style.produkItem}>Produk : {item.prod1},{item.prod2},{item.prod3},{item.prod4}</Text>
</View>
</View>)}
keyExtractor={item => item.id}
/>
)
}
return (
<ImageBackground source={require('../../assets/background.jpg')} resizeMode="cover" style={style.imageBackground}>
<View style={style.container}>
<View style={style.buttonContainer}>
<View style={style.buttonView}>
<Text style={style.button}>APPROVE</Text>
{/* this will show checked item on checkbox */}
</View>
<View style={style.buttonView}>
<Text style={style.button}>REJECT</Text>
</View>
</View>
<ScrollView>
{renderFlatlist(datas)}
</ScrollView>
</View>
</ImageBackground>
);
};
export default SubmitVerKunjungan;
Do the simple trick
Add state in your dataset
or
setData(Data.map(item => {item.state = false; return item;}));
Then in checkbox
<Checkbox value={item.state} onPress={() => handleCheckbox(item)}
const handleCheckbox = (item) => {
const index = datas.findIndex(x => x === item);
const datasClone = [...datas];
datasClone[index].state = !datasClone[index].state;
setData(datasClone);
}
Get all the selected ones
const handleSubmit = () => {
const selectedOnes = datas.filter(x => x.state);
console.log(selectedOnes);
}

Add a button "see more" in FlatList?

I use flatList to make a list of elements. I would like to show 15 elements and then add a button "see more" to show the next 15 etc.
I was about tu use this tutorial : https://aboutreact.com/react-native-flatlist-pagination-to-load-more-data-dynamically-infinite-list/
But I don't need to use fetch, I already have set up the data (state.listData) and in fact, I'm a little lost on how to adapt it...
I thought that maybe anyone could help me a little.
Thanks a lot
this.state = {
selectedId: '',
setSelectedId:'',
listData:''
}
};
renderItem = ({ item }) => {
const backgroundColor = item.id === this.selectedId ? "transparent" : "fff";
return (
<View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
<Item
item={item}
onPress={() => this.props.navigation.navigate('UpdateTripsForm')}
style={{ backgroundColor }}
/>
<Image source={require("../../assets/images/arrow.png")} style={{width: 15, height:15, justifyContent: 'center'}}/>
</View>
);
};
initListData = async () => {
let list = await getFlights(0);
if (list) {
this.setState({
listData: list
});
}
};
render() {
return (
<SafeAreaView style={styles.container}>
<FlatList
data={this.state.listData}
renderItem={this.renderItem}
maxToRenderPerBatch={15}
keyExtractor={(item) => item.id}
extraData={this.selectedId}
/>
<TouchableOpacity
style={styles.touchable2}
onPress={() => this.props.navigation.goBack()}
>
<View style={styles.view2}>
<Text style={styles.textimg2}>
{i18n.t("tripsform.action.back")}
</Text>
</View>
<Image
source={require("../../assets/images/btn-background.png")}
style={styles.tripsimg2}
/>
</TouchableOpacity>
</SafeAreaView>
);
};
}
I just tried this thanks to #Pramod 's answer :
const Item = ({ item, onPress, style }) => (
<TouchableOpacity onPress={onPress} style={[styles.flightsListitem, style]}>
<Text style={styles.h4}>{item.id}</Text>
</TouchableOpacity>
);
export default class FlightsList extends Component {
constructor(props) {
super(props);
this.state = {
selectedId: '',
setSelectedId:'',
listData:'',
page:1,
perPage:2,
loadMoreVisible:true,
displayArray:[]
}
};
renderItem = ({ item }) => {
const backgroundColor = item.id === this.selectedId ? "transparent" : "fff";
return (
<View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
<Item
item={item}
onPress={() => this.props.navigation.navigate('UpdateTripsForm')}
style={{ backgroundColor }}
/>
<Image source={require("../../assets/images/arrow.png")} style={{width: 15, height:15, justifyContent: 'center'}}/>
</View>
);
};
initListData = async () => {
let list = await getFlights(0);
if (list) {
this.setState({
listData: list
});
}
};
componentDidMount(){
this.setNewData()
// console.log(tempArray)
}
setNewData(){
var tempArray=[]
if(this.state.listData.length == this.state.displayArray.length){
this.setState({
loadMoreVisible:false
})
}else{
for(var i=0; i<(this.state.page*this.state.perPage); i++){
tempArray.push(this.state.listData)
}
this.setState({
displayArray: tempArray,
loadMoreVisible:true
})
}
}
loadMore(){
this.setState({
page: this.state.page+1
},()=>{
this.setNewData()
})
}
async UNSAFE_componentWillMount() {
this.initListData();
}
render() {
return (
<ImageBackground
source={require("../../assets/images/background.jpg")}
style={styles.backgroundImage}
>
<Header
backgroundImage={require("../../assets/images/bg-header.png")}
backgroundImageStyle={{
resizeMode: "stretch",
}}
centerComponent={{
text: i18n.t("mytrips.title"),
style: styles.headerComponentStyle,
}}
containerStyle={[styles.headerContainerStyle, { marginBottom: 0 }]}
statusBarProps={{ barStyle: "light-content" }}
/>
<SafeAreaView style={styles.container}>
<FlatList
data={this.state.displayArray}
renderItem={this.renderItem}
keyExtractor={(item) => item.id}
extraData={this.selectedId}
/>
{this.state.loadMoreVisible == true?
<Button style={{width:'100%', height:10, backgroundColor:'green', justifyContent:'center', alignItems:'center'}}
title = 'load more'
onPress={()=>{this.loadMore()}}>
</Button>:null}
<TouchableOpacity
style={styles.touchable2}
onPress={() => this.props.navigation.goBack()}
>
<View style={styles.view2}>
<Text style={styles.textimg2}>
{i18n.t("tripsform.action.back")}
</Text>
</View>
<Image
source={require("../../assets/images/btn-background.png")}
style={styles.tripsimg2}
/>
</TouchableOpacity>
</SafeAreaView>
</ImageBackground>
);
};
}
the flatlist is not displayed : I get :
You can user pagination method with per page limit so that you can have granular control
Load the array per page when component mount
On every click increase the per page and based on per page update data of your flat list
And also put a flag which will check when the data has ended which will help to hide the load more button when data ends
Working example: https://snack.expo.io/#msbot01/suspicious-orange
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
SafeAreaView,
SectionList,
Switch,
FlatList
} from 'react-native';
import Constants from 'expo-constants';
import Icon from 'react-native-vector-icons/FontAwesome';
import AwesomeIcon from 'react-native-vector-icons/FontAwesome';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
page:1,
perPage:2,
loadMoreVisible:true,
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',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'fourth Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'fifth Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29sd72',
title: 'sixth Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29dr72',
title: 'seventh Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d7w2',
title: 'Eight Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29ad72',
title: 'Nineth Item',
},
{
id: '58694a0f-3da1-471f-bd96-14557d1e29d72',
title: 'Tenth Item',
}],
displayArray:[]
}
}
componentDidMount(){
this.setNewData()
// console.log(tempArray)
}
setNewData(){
var tempArray=[]
if(this.state.DATA.length == this.state.displayArray.length){
this.setState({
loadMoreVisible:false
})
}else{
for(var i=0; i<(this.state.page*this.state.perPage); i++){
tempArray.push(this.state.DATA[i])
}
this.setState({
displayArray: tempArray,
loadMoreVisible:true
})
}
}
loadMore(){
this.setState({
page: this.state.page+1
},()=>{
this.setNewData()
})
}
render() {
return (
<View style={{ flex: 1 }}>
<FlatList
data={this.state.displayArray}
renderItem={({item})=>
<View style={{flexDirection:'row'}}>
<Text style={{fontSize:20}}>{item.title} </Text>
</View>
}
keyExtractor={item => item.id}
/>
{this.state.loadMoreVisible == true?
<View style={{width:'100%', height:10, backgroundColor:'green', justifyContent:'center', alignItems:'center'}} onClick={()=>{this.loadMore()}}>Load more</View>:null
}
</View>
);
}
}
Set data in state (already done ==> this.state.listData)
Set counter in state (initialize with 1)
Set 15 first elements in state (you can name it "renderedData" or something like that) and then increase cuonter to 1
Add a function that increases the "renderedData" by 15 items by increasing the counter by one
Add Footer component to the list which will call the function you created in stage 3
To take only 15( or 30/45/60 etc..) items from the list you can do something like this:
this.setState({ renderedItem: listData.slice(0, counter*15) })

Error with renderItem in React-native Flatlist

I'm trying to set up a flatlist to test it on a screen in React-native.
When I launch the emulator I'm getting this error : "Can't find variable renderItem" but I don't really know what's wrong with my code. It seemed that I had every element.
Is there someone that can help me ? Thanks a lot for any explanations or answer you can give to help.
import React, { Component } from "react";
import { Header } from "react-native-elements";
import {
FlatList,
SafeAreaView,
StatusBar,
StyleSheet,
Text,
ImageBackground,
View,
ScrollView,
Image,
TouchableOpacity
} from "react-native";
import i18n from "../../src/i18n";
import styles from "../../assets/Styles/Styles";
const DATA = [
{
id: "bd7acbea-c1b1-46c2-aed5-1",
title: "Test 1",
},
{
id: "3ac68afc-c605-48d3-a4f8-2",
title: "Test 2",
},
{
id: "58694a0f-3da1-471f-bd96-3",
title: "Test 3",
},
{
id: "58694a0f-3da1-471f-bd96-4",
title: "Test 4",
},
{
id: "58694a0f-3da1-471f-bd96-5",
title: "Test 5",
},
{
id: "58694a0f-3da1-471f-bd96-6",
title: "Test 6",
},
{
id: "58694a0f-3da1-471f-bd96-7",
title: "Test 7",
},
{
id: "58694a0f-3da1-471f-bd96-8",
title: "Test 8",
},
{
id: "58694a0f-3da1-471f-bd96-9",
title: "Test 9",
},
];
const Item = ({ item, onPress, style }) => (
<TouchableOpacity onPress={onPress} style={[styles.flightsListitem, style]}>
<Text style={styles.h3}>{item.title}</Text>
</TouchableOpacity>
);
export default class FlightsList extends Component {
constructor(props) {
super(props);
this.state = {
selectedId: '',
setSelectedId:''
}
};
renderItem = ({ item }) => {
const backgroundColor = item.id === selectedId ? "transparent" : "fff";
return (
<Item
item={item}
onPress={() => setSelectedId(item.id)}
style={{ backgroundColor }}
/>
);
};
render() {
return (
<ImageBackground
source={require("../../assets/images/background.jpg")}
style={styles.backgroundImage}
>
<Header
backgroundImage={require("../../assets/images/bg-header.png")}
backgroundImageStyle={{
resizeMode: "stretch",
}}
centerComponent={{
text: i18n.t("mytrips.title"),
style: styles.headerComponentStyle,
}}
containerStyle={[styles.headerContainerStyle, { marginBottom: 0 }]}
statusBarProps={{ barStyle: "light-content" }}
/>
<ScrollView style={styles.containerScrollNoMargins}>
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
/>
<TouchableOpacity
style={styles.touchable2}
onPress={() => this.props.navigation.goBack()}
>
<View style={styles.view2}>
<Text style={styles.textimg2}>
{i18n.t("tripsform.action.back")}
</Text>
</View>
<Image
source={require("../../assets/images/btn-background.png")}
style={styles.tripsimg2}
/>
</TouchableOpacity>
</SafeAreaView>
<Text>{"\n"}</Text>
</ScrollView>
</ImageBackground>
);
};
}
change
renderItem={renderItem}
to
renderItem={this.renderItem}
You must use renderItem={this.renderItem}
Because your renderItem function is not a variable or inner function of your render function. So, you must use this when you're trying to call another function of your class.

React Native - Getting an undefined returned value error from a built-in component

Error:Invariant Violation: Element type is invalid: expected a string .... but got: undefined.
The code in question is:
```
DefectDetails = (props) => {
if (props.currentStep != 2) {
return null;
}
return (
<View>
<Text style={styles.title}>Defect Details</Text>
<Text>Record the return state of the asset</Text>
<Picker
onValueChange={(itemValue, itemIndex) => this.setState({returnState:itemValue})}
>
<Picker.item value="null" label="Select return functionality"/>
<Picker.item value="0" label="Working"/>
<Picker.item value="1"label="Unservicable (red)"/>
<Picker.item value="2" label="Requires Attention (amber)"/>
</Picker>
<this.DefectDescription returnState={this.state.returnState}/>
</View>
)
}
DefectDescription = (props) => {
const returnState=this.props.returnState
if (returnState=="1"|returnState=="2") {
return (
<View>
<Text>Describe issue</Text>
<TextInput/>
</View>
) }
return null;
}
When I replace <this.DefectDescription/> with the expected return value of DefectDescription it all works fine.
Base code was generated via Expo and only App.js has been modified.
The full code is :
import React, { Component, useEffect } from 'react';
import {
StyleSheet,
TouchableOpacity,
Text,
TextInput,
View,
Button,
CheckBox,
Input,
Picker
} from 'react-native';
import * as assetData from './assets/assetData.json';
class App extends Component {
constructor(props) {
super(props);
this.state = {
asset_id: "TST-001-WD",
currentStep: 1,
assetRecord:assetData,
hasPermission: null,
setHasPermission: null,
scanned: false,
setScanned: false,
returnState:"null",
hasError: false,
}
console.log(this.state.assetRecord);
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
// Test current step with ternary
// _next and _previous functions will be called on button click
_next = () => {
let currentStep = this.state.currentStep;
// If the current step is 1 or 2, then add one on "next" button click
currentStep = currentStep >= 5? 6: currentStep + 1;
this.setState({
currentStep: currentStep
});
}
_prev = () => {
let currentStep = this.state.currentStep;
// If the current step is 2 or 3, then subtract one on "previous" button click
currentStep = currentStep <= 1? 1: currentStep - 1;
this.setState({
currentStep: currentStep,
});
}
previousButton() {
let currentStep = this.state.currentStep;
if(currentStep !==1){
return (
<TouchableOpacity
style={styles.button}
onPress={this._prev}
>
<Text>Previous</Text>
</TouchableOpacity>
);
}
return null;
}
nextButton(){
let currentStep = this.state.currentStep;
if(currentStep <2){
return (
<TouchableOpacity
style={styles.button}
onPress={this._next}
>
<Text>Next</Text>
</TouchableOpacity>
);
}
return null;
}
AssetDetails = (props) => {
if (props.currentStep != 1) {
return null;
}
return (
<View>
<Text style={styles.title}>Asset Details</Text>
<View style={{flexDirection: 'row',}}>
<Text style={styles.label}>Asset Id</Text>
<Text>{this.state.asset_id}</Text>
<TouchableOpacity
style={styles.button}
onPress={this.keyboardEntry}
>
<Text>Keyboard</Text>
</TouchableOpacity>
</View>
<View style={{flexDirection: 'row',}}>
<Text style={styles.label}>Manufacturer</Text>
<Text>{this.state.assetRecord.Manufacturer_name}</Text>
</View>
<View style={{flexDirection: 'row',}}>
<Text style={styles.label}>Product</Text>
<Text>{this.state.assetRecord.Asset_description}</Text>
</View>
<View style={{flexDirection: 'row',}}>
<Text style={styles.label}>Loan status</Text>
<Text>{this.state.assetRecord.loan_status}</Text>
</View>
<View style={{flexDirection: 'row',}}>
<Text style={styles.label}>Asset status</Text>
<Text>{this.state.assetRecord.Asset_Status_name}</Text>
</View>
<View style={{flexDirection: 'row',}}>
<Text style={styles.label}>RAG Status</Text>
<Text>{this.state.assetRecord.ragStatus}</Text>
</View>
</View>
)
}
DefectDetails = (props) => {
if (props.currentStep != 2) {
return null;
}
return (
<View>
<Text style={styles.title}>Defect Details</Text>
<Text>Record the return state of the asset</Text>
<Picker
onValueChange={(itemValue, itemIndex) => this.setState({returnState:itemValue})}
>
<Picker.item value="null" label="Select return functionality"/>
<Picker.item value="0" label="Working"/>
<Picker.item value="1"label="Unservicable (red)"/>
<Picker.item value="2" label="Requires Attention (amber)"/>
</Picker>
<this.DefectDescription returnState={this.state.returnState}/>
</View>
)
}
DefectDescription = (props) => {
const returnState=this.props.returnState
if (returnState=="1"|returnState=="2") {
return (
<View>
<Text>Describe issue</Text>
<TextInput/>
</View>
) }
return null;
}
render() {
return (
<View style={styles.container}>
<View>
<this.AssetDetails
currentStep={this.state.currentStep}
/>
<this.DefectDetails
currentStep={this.state.currentStep}
/>
</View>
<View style={{flexDirection: 'row',}}>
{this.previousButton()}
{this.nextButton()}
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
marginBottom: 10
},
title: {
alignItems: 'center',
padding: 10,
marginBottom: 10,
fontWeight: 'bold',
fontSize: 18,
},
label:{
paddingRight: 10,
},
row:{
paddingRight: 10,
flexDirection: 'row',
}
})
export default App;
The assetData.json file is:
{
"Asset_id": "23",
"Manufacturer_id": "44",
"Asset_Category_id": "32",
"Location_id": "7",
"Asset_Status_id": "4",
"Acquired_date": "2014-09-01",
"Disposal_date": "",
"External_Asset_id": "VEH-001-WD",
"Asset_description": "Transit tipper",
"Comment": "Donated - second hand",
"Last_serviced": "2017-04-11",
"Owner_id": "1",
"Serial_no": "",
"Manufacturer_name": "Ford",
"Asset_Category_name": "Vehicle",
"Location_name": "Western Depot",
"Recording": "Miles",
"derived_status": "3",
"RAGColour": "LightGreen",
"loan_status": "Checked out",
"last_miles_hours": "137",
"last_checklist": [{
"faultData": "true",
"lights": "true",
"tyres": "true"
}],
"last_return_time": "0000-00-00 00:00:00",
"category_list": null,
"Asset_Status_name": "Available subject to RAG",
"faultList": [{
"Asset_Defect_id": "7",
"status_id": "3",
"statusText": "Accepted (No action needed)",
"Fault_description": "Cracked windscreen"
}, {
"Asset_Defect_id": "13",
"status_id": "3",
"statusText": "Accepted (No action needed)",
"Fault_description": "The sticker has fallen off the tailgate"
}, {
"Asset_Defect_id": "29",
"status_id": "3",
"statusText": "Accepted (No action needed)",
"Fault_description": "Bonnet catch has fallen off"
}],
"checkList": [{
"checklist_item_id": "3",
"checklist_item_longtext": "Light check includes head lights, stop lights and indicators",
"checklist_item_title": "Lights",
"checklist_item_code": "lights",
"preChecked": ""
}, {
"checklist_item_id": "2",
"checklist_item_longtext": "Tyres must be checked for wear and pressure",
"checklist_item_title": "Tyres",
"checklist_item_code": "tyres",
"preChecked": ""
}]
}
I am very much a new developer with this tool set and It probably something very simple, but I've been puzzling over this for two days now
It should be <DefectDescription /> not <this.DefectDescription/>

React Native FlatList Touchable Opacity

I used FlatList to display the title that is in the data. I added in TouchableOpacity for the FlatList. So for example, when I click 'First', I want to show the the data from 'mood' and it will show the list of passionate,rousing and confident. I want to show the list on a new file/screen and show purely the mood of list.
This is my data:
const Mock =
[
{ title: 'First',
mood:
[
{name: 'passionate'},
{name: 'rousing'},
{name: 'confident'},
],
},
{ title: 'Second',
mood:
[
{name: 'rollicking'},
{name: 'cheerful'},
{name: 'fun'},
{name: 'sweet'},
{name: 'amiable'},
{name: 'natured'}
],
This is my FlatList code:
export default class Cluster1 extends Component{
render() {
return (
<View>
<FlatList
data={Mock}
renderItem={({ item, index }) => {
return <FlatListItem item={item} index={index} />;
}}
/>
</View>
);
}
}
class FlatListItem extends Component {
render() {
return (
<View style={styles.list}>
<View>
<TouchableOpacity>
<Text style={styles.itemTitle}>{this.props.item.title}</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
What should I do with the TouchableOpacity when I want to show the mood name when I click the title?
This is my style code
const styles = StyleSheet.create({
itemTitle:{
fontSize: 25,
fontWeight: 'bold',
color: 'white',
margin: 20,
},
},
list:{
flex: 1,
backgroundColor: '#00BCD4',
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
},
});
You should modify your code as below to do this:
export default class Cluster1 extends Component {
render() {
return (
<View style={{ margin: 30, backgroundColor: '#ddd' }}>
<FlatList
data={Mock}
renderItem={({ item, index }) => {
return <FlatListItem item={item} index={index} />;
}}
/>
</View>
);
}
}
class FlatListItem extends Component {
state = { showItemIndex: [false, false] };
_onPress = index => () => {
let showItemIndex = this.state.showItemIndex;
showItemIndex[index] = !this.state.showItemIndex[index];
this.setState({ showItemIndex });
};
render() {
return (
<View style={styles.list}>
<View>
<TouchableOpacity onPress={this._onPress(this.props.index)}>
<Text style={styles.itemTitle}>{this.props.item.title}</Text>
</TouchableOpacity>
{this.state.showItemIndex[this.props.index] && (
<FlatList
data={this.props.item.mood}
extraData={this.state.showItemIndex}
renderItem={({ item, index }) => {
return (
<Text item={item} index={index}>
{item.name}
</Text>
);
}}
/>
)}
</View>
</View>
);
}
}
Use this, it's should be work fine for you:
Link: https://github.com/oblador/react-native-collapsible
Link: https://github.com/naoufal/react-native-accordion
Link: https://github.com/cuiyueshuai/react-native-expandable-section-flatlist
You could set a state variable which gets updated whenever your TouchableOpacity gets pressed. And then you conditionally render the title or the list of mood names:
class FlatListItem extends Component {
constructor(props) {
super(props);
this.state = {collapsed: true}
}
render() {
return (
<View style={styles.list}>
<View>
<TouchableOpacity
onPress={this.onPress}
>
<Text style={styles.itemTitle}>
{this.props.item.title}
</Text>
</TouchableOpacity>
{this.state.collapsed ?
<View /> :
<View>
{this.props.item.mood.map(mood => <Text>{mood.name}</Text>)}
</View>}
</View>
</View>
);
}
onPress = () => {
this.setState({collapsed: !this.state.collapsed})
}
}
You can do this by separating out the datasource that is required to show in the list.
First to display title: you can do something like this
export default class Cluster1 extends Component {
state = {
data: []
};
componentWillMount() {
const titles = Mock.forEach(data => data.title);
this.setState({
data: titles
});
}
onItemClick = item => {
const itemIndex = Mock.findIndex(data => (
data.title === item
));
const values = Mock[itemIndex].mood;
this.setState({
data: values
});
};
render() {
return (
<View>
<FlatList
data={this.state.data}
renderItem={({ item, index }) => {
return (
<FlatListItem
item={item}
index={index}
onItemClick={this.itemClick}
/>
);
}}
/>
</View>
);
}
}
and then in your FlatlistItem code:
class FlatListItem extends Component {
render() {
return (
<View style={styles.list}>
<View>
<TouchableOpacity onPress={() =>
this.props.onItemClick(this.props.item)
}>
<Text style={styles.itemTitle}>
{
this.props.item.name ?
this.props.item.name : this.props.item
}
</Text>
</TouchableOpacity>
</View>
</View>
);
}
}