React Native Search using SectionList - react-native

I created a SectionList and tried to implement a search filter for my SectionList. But my output got an error. I took a screenshot of it below. I don't know what's wrong.
This is my component.
export default class Cluster1 extends Component{
constructor(props){
super(props)
this.state = {
dataToShow: '',
search: false
}
}
searchUpdated = (term) => {
let matchedItemsArray = []
if(term === ''){
this.setState({search: false, dataToShow: ClusterData})
}else{
this.state.dataToShow.map((item) => {
if(item.title.includes(term)){
matchedItemsArray.push(item)
}
})
this.setState({search: true, dataToShow: matchedItemsArray})
}
}
searchUpdated = (input) => {
let userInput =[]
if(input === ''){
this.setState({search: false})
userInput = ''
}else{
this.setState({search: true})
}
}
render(){
return(
<View style={styles.container}>
<TextInput
onChangeText={(term) => { this.searchUpdated(text) }}
style={styles.searchInput}
placeholder="Type a mood to search"
/>
<SectionList
renderItem = {({item, index}) =>
<SectionListItem item = {item} index = {index}/>}
renderSectionHeader = {({section}) =>
<SectionHeader
sections={this.searchUpdated()}
keyExtractor = {(item) => item.name}/>}>
</SectionList> </View>
);
}}
class SectionHeader extends Component {
render() {
return (
<View style={styles.header}>
<Text style={styles.headertext}>
{this.props.section.title}
</Text>
<TouchableOpacity onPress={ () => Actions.SongList({ section: this.props.section}) }>
<Text style ={styles.Play}> Play
</Text>
</TouchableOpacity>
</View>
); }
}
class SectionListItem extends Component{
render(){
return(
<View>
<Text style={styles.moodname}>{this.props.item.name}</Text>
</View>
);
}}
This is my data
const ClusterData = [
{ title: 'Cluster1',
data:
[
{name: 'passionate'},{name: 'rousing'},{name: 'confident'},
{name: 'boisterous'},{name: 'rowdy'}],
},
{
title: 'Cluster2',
data:
[
{name: 'rollicking'},{name: 'cheerful'{name: 'fun'},{name: 'sweet'},
{name: 'amiable'},{name: 'natured'}],

Here is a simple search filter:
I added a search state to help determine whether the user is currently searching or not.
constructor(props){
super(props)
this.state = {
dataToShow: '',
search: false
}
}
Then, we create the search function.
searchUpdated = (term) => {
let matchedItemsArray = []
if(term === ''){
this.setState({search: false, dataToShow: ClusterData})
}else{
this.state.dataToShow.map((item) => {
if(item.title.includes(term)){
matchedItemsArray.push(item)
}
})
this.setState({search: true, dataToShow: matchedItemsArray})
}
}
When the input is '', the search state is false. Otherwise, the function will map through the dataToShow array to find if any section titles include the user's input.
Alternatively, I like to use a lodash filter instead for it's simplicity.
First, we declare a constant called userInput:
let userInput
Then, we create a function to determine whether the userInput is empty or not to set the search state. (Remember to keep this.state.search that we created in the first place)
searchUpdated = (input) => {
if(input === ''){
this.setState({search: false})
userInput = ''
}else{
this.setState({search: true})
}
}
Finally, in our SectionList we use the lodash filter to help filter for the right section header names:
<SectionList
renderItem = {({item, index}) =>
<SectionListItem item = {item} index = {index}/>}
renderSectionHeader = {({section}) =>
<SectionHeader
section = {section}
sections = {
this.state.search ?
_.filter(this.state.dataToShow, function(item){
return item.title.includes(userInput)})
: this.state.dataToShow}
keyExtractor = {(item) => item.name}/>}>
</SectionList>
The entire component
import React from 'react'
import { View, Text, SectionList, TouchableOpacity, TextInput } from 'react-native'
const ClusterData = [
{title: 'Cluster1', data: [{name: 'passionate'},{name: 'rousing'},{name: 'confident'},{name: 'boisterous'},{name: 'rowdy'}]},
{title: 'Cluster2', data: [{name: 'rollicking'},{name: 'cheerful'},{name: 'fun'},{name: 'sweet'},{name: 'amiable'},{name: 'natured'}]}
]
let userInput = ''
export default class TempScreen extends React.Component {
constructor(props){
super(props)
this.state = {
search: false,
dataToShow: []
}
}
componentWillMount(){
this.setState({dataToShow: ClusterData})
}
searchUpdated = (term) => {
let matchedItemsArray = []
if(term === ''){
this.setState({search: false, dataToShow: ClusterData})
}else{
this.setState({search:true, dataToShow: ClusterData}, function(){
this.state.dataToShow.map((item) => {
if(item.title.includes(term)){
matchedItemsArray.push(item)
}
})
this.setState({dataToShow:matchedItemsArray})
})
}
}
render () {
return (
<View>
<TextInput
onChangeText={(term) => {this.searchUpdated(term)}}
style={styles.searchInput}
placeholder="Type a mood to search"/>
<SectionList
renderItem={({item}) => <SectionListItem itemName = {item.name}/>}
renderSectionHeader={({section}) => <SectionHeader sectionTitle = {section.title}/>}
sections={this.state.dataToShow}
/>
</View>
)
}
}
class SectionHeader extends React.Component{
render(){
return(
<View>
<Text>{this.props.sectionTitle}</Text>
<TouchableOpacity>
<Text>Play</Text>
</TouchableOpacity>
</View>
)
}
}
class SectionListItem extends React.Component{
render(){
return(
<View>
<Text>{this.props.itemName}</Text>
</View>
)
}
}

Related

how to pass props from flatlist to search?

I have my Main function in one file:
import Search from '../Components/Header';
function Main() {
return (
<View>
<Search />
<FlatList
data={this.state.data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
style={{borderColor: 'black', borderWidth: 1, flexWrap: 'wrap'}}
/>
</View>
And Search class in another file:
const DATA = [
{
id: "1",
title: "Data",
}
];
const Item = ({ title }) => {
return (
<View>
<Text>{title}</Text>
</View>
);
};
const renderItem = ({ item }) => <Item title={item.title} />;
export default class Search extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
data: DATA,
error: null,
searchValue: "",
};
this.arrayholder = DATA;
};
searchFunction = (text) => {
const updatedData = this.arrayholder.filter((item) => {
const item_data = `${item.title.toUpperCase()})`;
const text_data = text.toUpperCase();
return item_data.indexOf(text_data) > -1;
});
this.setState({ data: updatedData, searchValue: text });
};
render() {
return (
<View style={Headerstyles.rectangle}>
<SearchBar
value={this.state.searchValue}
onChangeText={(text) => this.searchFunction(text)}
/>
</View>
);
}
}
So as I understand I should pass props from Flatlist to Search class, but I get an error TypeError: Cannot read property 'data' of undefined. I think it's not only about data and also renderItem and keyExtractor.
How can I do this?
The component Main does not contain a state called data. This state is defined in Search. I would create the state inside Main and pass the setter function to Search.
function Main() {
const [data, setData] = React.useState(DATA);
return (
<View>
<Search setData={setData} />
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
style={{borderColor: 'black', borderWidth: 1, flexWrap: 'wrap'}}
/>
</View>
)
}
Then, use the new props in Search as follows.
export default class Search extends Component {
constructor(props) {
super(props);
this.state = {
loading: false,
error: null,
searchValue: "",
};
this.arrayholder = DATA;
};
searchFunction = (text) => {
const updatedData = this.arrayholder.filter((item) => {
const item_data = `${item.title.toUpperCase()})`;
const text_data = text.toUpperCase();
return item_data.indexOf(text_data) > -1;
});
this.setState({ searchValue: text });
this.props.setData(updatedData);
};
render() {
return (
<View style={Headerstyles.rectangle}>
<SearchBar
value={this.state.searchValue}
onChangeText={(text) => this.searchFunction(text)}
/>
</View>
);
}
}

ReferenceError: Can't find variable: films in Autocomplete

I need to use an autocomplete in my app,
I'm using this library because it was the only one I found
https://www.npmjs.com/package/react-native-autocomplete-input
and this way it is working.
import React, { Component } from 'react';
import Autocomplete from 'react-native-autocomplete-input';
export default class Registrar extends Component{
state = {
films: [],
query: '',
}
componentDidMount() {
const json = require('../assets/json/titles.json');
const { results: films } = json;
this.setState({ films });
}
findFilm(query) {
if (query === '') {
return [];
}
const { films } = this.state;
const regex = new RegExp(`${query.trim()}`, 'i');
return films.filter(film => film.title.search(regex) >= 0);
}
render() {
const { query } = this.state;
const films = this.findFilm(query);
const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();
return(
<Autocomplete
autoCapitalize="none"
style={styles.input}
autoCorrect={false}
data={films.length === 1 && comp(query, films[0].title) ? [] : films}
defaultValue={query}
onChangeText={text => this.setState({ query: text })}
placeholder="Enter the film title"
renderItem={({ item }) => (
<TouchableOpacity onPress={() => this.setState({ query: item.title })}>
<Text style={styles.itemText}>
{item.title} ({item.release_date})
</Text>
</TouchableOpacity>
)}
/>
}
}
However, my code requires to be inside a function, as in the example below, but it generates the following error ReferenceError: Can't find variable: films
import React, { Component } from 'react';
import Autocomplete from 'react-native-autocomplete-input';
export default class Registrar extends Component{
state = {
films: [],
query: '',
}
componentDidMount() {
const json = require('../assets/json/titles.json');
const { results: films } = json;
this.setState({ films });
}
findFilm(query) {
if (query === '') {
return [];
}
const { films } = this.state;
const regex = new RegExp(`${query.trim()}`, 'i');
return films.filter(film => film.title.search(regex) >= 0);
}
renderInputField() {
return (
<Autocomplete
autoCapitalize="none"
style={styles.input}
autoCorrect={false}
data={films.length === 1 && comp(query, films[0].title) ? [] : films}
defaultValue={query}
onChangeText={text => this.setState({ query: text })}
placeholder="Enter the film title"
renderItem={({ item }) => (
<TouchableOpacity onPress={() => this.setState({ query: item.title })}>
<Text style={styles.itemText}>
{item.title} ({item.release_date})
</Text>
</TouchableOpacity>
)}
/>
)
}
render() {
const { query } = this.state;
const films = this.findFilm(query);
const comp = (a, b) => a.toLowerCase().trim() === b.toLowerCase().trim();
return(
{this.renderInputField()}
}
}
I need it to be within a function because this field must appear when answering yes in the previous question
Please, Help me!
Can you try like following. Just add construtor to your class
export default class Registrar extends Component{
construtor(props){
super(props)
this.state = {
films: [],
query: '',
}
}
}
Otherwise check the error line number(it will display with the error), then you can easily find out where its occurred.

Redux didn't update component

I'm pretty new in React-Native. I'm trying to display a list of devices, then go to one device, go to its informations, change the name, and with redux to change the name on all "screens" but it didn't work. I thing I a little bit lost between props, state and global state...
All the navigation, views and APIs works well.
This is my list view:
class DeviceList extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
};
this._getDevices();
// BINDING
this._goToDevice = this._goToDevice.bind(this);
this._goToDeviceAdd = this._goToDeviceAdd.bind(this);
}
componentDidUpdate() {
console.log("DEVICE_LIST componentDidUpdate : ");
console.log(this.props.devices);
}
_goToDevice(id = number) {
this.props.navigation.navigate('DeviceDetail', { idDevice: id })
}
_getDevices() {
restGet('devices')
.then(data => {
// REDUX
const action = { type: "INIT_DEVICE_LIST", value: data.datas };
this.props.dispatch(action);
// STATE
this.setState({
isLoading: false
});
});
}
_displayList() {
if (!this.state.loading && this.props.devices && this.props.devices.length > 0) {
return (
<View style=>
<FlatList
// data={this.state.devices}
data={this.props.devices}
keyExtractor={(item) => item.id.toString()}
renderItem={({item}) => <DeviceItem device={item} goToDevice={this._goToDevice}
/>}
/>
</View>
)
}
}
render() {
return (
<View style={styles.main_container}>
{/* LOADING */}
<Loading loading={this.state.isLoading}/>
{/* LIST */}
{this._displayList()}
</View>
);
}
}
// REDUX
const mapStateToProps = (state) => {
return {
devices: state.devices
};
};
export default connect(mapStateToProps)(DeviceList);
This is my Device Detail screen:
class DeviceDetail extends React.Component {
constructor(props) {
super(props);
this.state = {
device: null,
isLoading: true,
};
//
this._getDevice();
}
componentDidUpdate() {
console.log("DEVICE_DETAIL componentDidUpdate : ");
console.log(this.props.devices);
}
_goToDeviceInfo() {
this.props.navigation.navigate('DeviceInfo', { deviceId: this.state.device.id })
}
_getDevice() {
restGet('devices/' + this.props.navigation.getParam('idDevice'))
.then(data => {
// REDUX
const action = { type: "UPDATE_DEVICE", value: data.datas };
this.props.dispatch(action);
// STATE
this.setState({
device: this.props.devices.find(d => d.id === this.props.navigation.getParam('idDevice')),
isLoading: false,
});
});
}
_displayTile() {
if (this.state.device) {
return (
<View>
<Text>{this.state.device.name}</Text>
<TouchableOpacity onPress={() => this._goToDeviceInfo()}>
<FontAwesomeIcon icon={ faCog } size={ 18 } />
</TouchableOpacity>
</View>
)
}
}
render() {
return (
<View style={styles.main_container}>
{/* LOADING */}
<Loading loading={this.state.isLoading}/>
{/* TILE */}
{this._displayTile()}
</View>
);
}
}
// REDUX
const mapStateToProps = (state) => {
return {
devices: state.devices
};
};
export default connect(mapStateToProps)(DeviceDetail);
My Device Info Screen
class DeviceInfo extends React.Component {
constructor(props) {
super(props);
this.state = {
// device: this.props.navigation.getParam('device')
// device: this.props.devices.find(d => d.id === this.props.navigation.getParam('deviceId')),
};
// BINDING
this._saveItem = this._saveItem.bind(this);
}
componentDidUpdate() {
console.log("DEVICE_INFO componentDidUpdate : ");
console.log(this.props.devices);
}
_saveItem(name) {
// DB
// restPost('devices', {'id': this.state.device.id, 'name': name})
console.log();
restPost('devices', {'id': this.props.devices.find(d => d.id === this.props.navigation.getParam('deviceId')).id, 'name': name})
.then(data => {
// REDUX
const action = { type: "UPDATE_DEVICE", value: data.datas };
this.props.dispatch(action);
});
}
_removeDevice() {
Alert.alert(
'Supprimer l\'Appareil',
'Voulez-vous vraiment supprimer cet Appareil ?',
[
{
text: 'Annuler',
style: 'cancel',
onPress: () => console.log('Cancel Pressed'),
},
{
text: 'Oui, je souhaite le supprimer.',
onPress: () => {
// REDUX
const action = { type: "DELETE_DEVICE", value: this.state.device };
this.props.dispatch(action);
this.props.navigation.navigate('DeviceList')
}
},
],
{cancelable: false},
);
}
render() {
// const device = this.state.device;
const device = this.props.devices.find(d => d.id === this.props.navigation.getParam('deviceId'));
return (
<View style={ styles.main_container }>
<DeviceInfoItem device={device} title={'NOM'} value={device.name} edit={true} saveItem={this._saveItem}/>
<View style={styles.footer}>
<TouchableOpacity style={styles.startButton} onPress={() => this._removeDevice()}>
<FontAwesomeIcon icon={ faTrash } style={styles.footer_element_icon}/>
<Text style={styles.footer_element_text}>Supprimer l'Appareil</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
// REDUX
const mapStateToProps = (state) => {
return {
devices: state.devices
};
};
export default connect(mapStateToProps)(DeviceInfo);
My Device Info Item Component
class DeviceInfoItem extends React.Component {
constructor(props) {
super(props);
this.state = {
displayForm: false,
};
this.editText = '';
console.log(this.props);
}
componentDidUpdate() {
console.log("DEVICE_INFO_ITEM componentDidUpdate");
}
_displayValue() {
if (this.props.edit && this.state.displayForm) {
return (
<View>
<Input
placeholder={this.props.title}
// value={value}
leftIcon={<FontAwesomeIcon icon={ faTag } size={ 10 } />}
leftIconContainerStyle={ styles.inputIcon }
onChangeText={(text) => {
this.editText = text;
}}
/>
</View>
);
} else {
return (
<View>
<Text style={ styles.title }>{ this.props.title }</Text>
<Text style={ styles.value }>{ this.props.value }</Text>
</View>
);
}
}
_displayButton() {
if (this.props.edit) {
if (!this.state.displayForm) {
return (
<TouchableOpacity style={styles.edit} onPress={() => {
this.setState({
displayForm: true
})
}}>
<FontAwesomeIcon icon={ faPen } style={ styles.info_icon } size={ 14 } />
</TouchableOpacity>
);
} else {
return (
<TouchableOpacity style={styles.edit} onPress={() => {
this.props.saveItem(this.editText);
this.setState({
displayForm: false,
});
}}>
<FontAwesomeIcon icon={ faCheck } style={ styles.info_icon } size={ 14 } />
</TouchableOpacity>
);
}
}
}
render() {
return (
<View>
<View style={ styles.line }>
{ this._displayValue() }
{ this._displayButton() }
</View>
<Divider style={ styles.divider } />
</View>
);
}
}
export default DeviceInfoItem;
And my reducer:
const initialState = {
devices: []
};
function updateDevices(state = initialState, action) {
let nextState;
// CHECK IF DEVICE EXIST
const deviceIndex = state.devices.findIndex(device => device.id === action.value.id);
let device = state.devices.find(device => device.id === action.value.id);
switch (action.type) {
case 'INIT_DEVICE_LIST':
console.log('INIT_DEVICE_LIST');
nextState = {
...state,
devices: action.value
};
return nextState || state;
case 'ADD_DEVICE':
console.log('ADD_DEVICE');
nextState = {
...state,
devices: [...state.devices, action.value]
};
return nextState || state;
case 'DELETE_DEVICE':
console.log('DELETE_DEVICE');
if (deviceIndex !== -1) {
nextState = {
...state,
devices: state.devices.filter( (item, index) => index !== deviceIndex)
}
}
return nextState || state;
case 'UPDATE_DEVICE':
console.log('UPDATE_DEVICE');
if (deviceIndex !== -1) {
let d = state.devices;
d[deviceIndex] = action.value;
nextState = {
...state,
devices: d
}
}
return nextState || state;
default:
return state
}
}
export default updateDevices;
Delete Device works very well, the devices list in well updated. But the name updating didn't work. When I save, I got a console log ('DEVICE_INFO_ITEM componentDidUpdate) but not ('DEVICE_INFO componentDidUpdate). Why ?
create a file index.js in your reducer folder and do this:
import { combineReducers } from 'redux';
import myreducer from './Reducerfile';
export default combineReducers({
reducer: myreducer
});
And then
// REDUX
const mapStateToProps = (state) => {
return {
devices: state.reducer.devices
};
};
export default connect(mapStateToProps)(DeviceInfo);

Why react-native doesn't render all content when 2 render methods included in it?

I have some content to be rendered conditionally and some fixed content i.e. footer. I dont want to render footer every time when state changes, hence I've added two methods renderContent() and renderFooter to be called in render() method.
Below code, doesn't render both methods.
'use strict';
import React, { Component } from 'react';
import { Alert, FlatList, View, StyleSheet, Text, Linking, Button } from 'react-native';
import { AsyncStorage } from 'react-native';
import getEnvVars from '../environment';
const { apiUrl } = getEnvVars();
import Moment from 'moment';
import { Ionicons } from '#expo/vector-icons';
import FootBar from '../screens/FootBar';
import { LinesLoader } from 'react-native-indicator';
export default class SubscriptionsToEnd extends Component {
static navigationOptions = ({ navigation }) => {
const { state } = navigation;
return {
title: `${state.params && state.params.title ? state.params.title : 'Subscriptions Due'}`,
};
};
constructor(props) {
super(props);
this.state = {
isLoaded: false,
dataSource: [],
title: 'Subscriptions Due'
};
}
componentDidMount() {
this._getAllCustomers();
}
_getAllCustomers() {
let url;
if (this.state.title === 'Subscriptions Due') {
url = apiUrl + "/customersWithSubscriptionNearToEnd/";
this.props.navigation.setParams({ title: 'Subscriptions Due' })
}
if (this.state.title === 'Customers') {
url = apiUrl + "/customers/";
this.props.navigation.setParams({ title: 'Customers' })
}
this.setState({ isLoaded: false })
try {
AsyncStorage.multiGet(['role', 'jwt']).then((data) => {
let role = data[0][1];
let jwt = data[1][1];
if (role === 'Admin') {
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'jwt': jwt
},
}).then(res => res.json())
.then(
(result) => {
if (result.message != 'Unauthorized user!' && this.state.title === 'Customers') {
this.setState({
isLoaded: true,
dataSource: result,
title: 'Subscriptions Due'
});
} else if (result.message != 'Unauthorized user!' && this.state.title === 'Subscriptions Due') {
this.setState({
isLoaded: true,
dataSource: result,
title: 'Customers'
});
} else if (result.message === 'Unauthorized user!') {
this.props.navigation.navigate('Login');
}
},
(error) => {
console.log(error);
this.setState({
isLoaded: true
});
this.props.navigation.navigate('Login');
}
)
}
})
} catch (error) {
console.log('Error at getting token \n' + error)
}
}
GetGridViewItem(id) {
Alert.alert(id);
}
_logOutAsync = async () => {
await AsyncStorage.clear();
this.props.navigation.navigate('Auth');
};
_addCustomer() {
// TBD
}
renderContent() {
if (!this.state.isLoaded) {
return (
<View style={styles.loader}>
<LinesLoader color='#1d91a5' barWidth={5} barHeight={60} barNumber={5} betweenSpace={5} />
</View>
)
}
if (this.state.isLoaded) {
return (
<View style={styles.container}>
<View style={styles.grid}>
<FlatList
data={this.state.dataSource}
renderItem={({ item }) =>
<View style={styles.GridViewContainer}>
<Text style={styles.GridViewTextLayout}>
<Text onPress={this.GetGridViewItem.bind(this, item._id)}>
<Text style={styles.Name}>{item.firstname}</Text> <Text style={styles.Name}>{item.lastname}</Text> {"\n"}
<Text>{Moment(item.till_date).format('Do MMM YYYY')} </Text>{"\n\n"}
</Text>
<Text onPress={() => { Linking.openURL('tel:+44' + item.mobile); }}><Ionicons name="md-phone-portrait" size={22} color="#1d91a5" /> {item.mobile}</Text> {"\n\n"}
<Text><Ionicons name="md-mail" size={22} color="#1d91a5" />{item.email}</Text>
</Text>
</View>}
numColumns={2}
keyExtractor={(item, index) => index.toString()}
/>
</View >
</View>
)
};
}
renderFooter() {
return (
<View style={styles.buttonsContainer}>
<View style={styles.button}>
<Button color='#1d91a5' title={this.state.title} onPress={this._getAllCustomers.bind(this)} />
</View>
<View style={styles.button}>
<Button color='#1d91a5' title="+Customer" onPress={this._addCustomer.bind(this)} />
</View>
<View style={styles.button}>
<Button color='#1d91a5' title="Logout" onPress={this._logOutAsync.bind(this)} />
</View>
</View>
);
}
render() {
return (
this.renderContent(),
this.renderFooter()
);
}
}
Above code only renders this.renderFooter() method. If I swap methods in render(), it renders this.renderContent().
Can someone please tell me why it is failing to render both?
I was doing it wrong. Main render() method should be like:
render() {
return (
<View style={styles.wrapper}>
{this.renderContent()}
{this.renderFooter()}
</View>
);
}
It looks like you figured it out just before I could post my answer.
The return function can only return one view. Your 2 functions each return a view. So wrapping both functions in a single view solves the problem.

passing extraData to FlatList isn't working

I followed https://facebook.github.io/react-native/releases/next/docs/flatlist.html to make a FlatList and also passed this.state to extraData but still, once I delete an item, the item is still shown. I have also logged this.state to make sure the item is deleted and it indeed did. My code is below:
class DescriptionItem extends React.PureComponent {
render() {
return (
<TouchableOpacity
style={this.props.containerStyle}
onPress={(event) => {this.props.onPress(this.props.value)}}>
<Text style={this.props.style}>{this.props.value}</Text>
</TouchableOpacity>
)
}
}
export default class CardWorkDescriptionsList extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
loading: false,
data: [],
error: null,
refreshing: false,
};
}
_notifyItemSelected(text) {
if(this.props.onItemSelected) {
this.props.onItemSelected(text)
}
}
_onItemSelected = (selectedItem) => {
var array = this.state.data;
var index = array.indexOf(selectedItem)
array.splice(index, 1);
console.log(array)
this.setState({data: array });
console.log("yeah",this.state.data)
this._notifyItemSelected(selectedItem);
}
makeRemoteRequest = () => {
//TODO: fetch data
this.setState({data: descriptionsFake})
}
componentDidMount() {
this.makeRemoteRequest();
}
render() {
return (
<View style={styles.cardLight}>
<FlatList
data={this.state.data}
extraData={this.state}
renderItem={(item) => (
<DescriptionItem
containerStyle={styles.itemContainer}
style={styles.content}
value={item.item}
onPress={(selectedItem)=>this._onItemSelected(selectedItem)}/>
)}
keyExtractor={item => item.substring(0,20)}
/>
</View>
);
}
}
Try extending React.Component instead of PureComponent