0

I'm trying to render a Flatlist that contains a store name. Upon clicking the store name, more information about the store should be displayed.

I attempted to change state and then use

{this.renderMoreDetails(item) && this.state.moreDetailsShown}

to get the additional information to appear. However, it was clear via console.log that state was only changed after a second button press.

From what I read in this article 1 and this article 2 it seemed as though I needed a callback function as an additional parameter to my setState().
I tried adding a callback function(probably incorrect, but I'm extremely lost at this point) and only got more errors.

I know that I have access to all of the data from renderItem inside FlatList. How do I make it appear upon click?

    import React, { Component } from 'react';
import { 
        View,
        FlatList,
        Text,
        TouchableWithoutFeedback,
        ListView,
        ScrollView
        } from 'react-native'

import { NavigationActions } from 'react-navigation';
import { Header, Card, CardSection } from '../common';
import Config from '../Config';

export default class Costco extends Component<Props> {
    constructor(props) {
        super(props);
        this.state = {
            stores: [],
            selectedItem: {id: null},
        };
    }

    componentWillMount() {
        const obj = Config.costcoThree;
        const costcoArr = Object.values(obj);

        this.setState({
            stores: costcoArr,
        })

    }

    renderListOfStores() {
        return <FlatList 
          data={this.state.stores} 
          renderItem={ ({item}) => this.singleStore(item)} 
          keyExtractor={(item) => item.id} 
          extraData={this.state.selectedItem} />
    }

    singleStore(item) {
        console.log(this.state.selectedItem.id)
        return item.id === this.state.selectedItem.id ?
            <TouchableWithoutFeedback

                onPress={() => this.selectStore(item)}
            >
                <View>
                    <Text>{item.branchName}</Text>
                    <Text>Opening Time {item.openingTime}</Text>
                    <Text>Closing Time {item.closingTime}</Text>
                    <Text>Address {item.dongAddKor}</Text>
                </View>
            </TouchableWithoutFeedback>
        : 
        <TouchableWithoutFeedback>
            <View>
                <Text>{item.branchName}</Text>
                <Text>Only showing second part</Text>
            </View>
        </TouchableWithoutFeedback>

    }

    selectStore(item) {

        this.setState({selectedItem: item});
        console.log('repssed');
    }

    render() {
        return(
            <ScrollView> 
                <Header headerText="Costco"/>
                <Text>hello</Text>
                {this.renderListOfStores()}
            </ScrollView>
        )
    }
}
VK1
  • 1,676
  • 4
  • 28
  • 51
  • use extraData = {this.state} in flatlist props. And no need to call more data function in onPress callback.. JSX condition is enough for it. – tahir mahmood Feb 22 '18 at 11:11
  • Thank you for responding. I removed this.renderMoreDetails(item) from the onPress handler. I also added extraData={this.state} to the FlatList props. Unfortunately, state still does not change until the second button press and additional information does not get rendered. – VK1 Feb 22 '18 at 11:23

1 Answers1

2

as a workaround you can have a state that maintain your selected item to expand(or something like another view) and then you can use some conditions to work for render your flat list data.

Consider the below code and let me know if you need some more clarification.

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,FlatList,TouchableNativeFeedback,
  View
} from 'react-native';

export default class App extends Component<Props> {

    constructor(props) {
      super(props);

      this.state = {
        response: [],
        selectedItem: {id: null},
      };
    }


    userListLayout() {
        const {response} = this.state;
        return <FlatList data={response} renderItem={ ({item}) => this.singleUserLayout(item)} keyExtractor={(item) => item.email} extraData={this.state.selectedItem} />
    }


    singleUserLayout(item) {
        return item.id == this.state.selectedItem.id ? 
            <TouchableNativeFeedback onPress={() => this.userSelected(item)}>
            <View style={{flex:1, borderColor: 'black', borderWidth: 1}}>
            <Text style={{padding: 10, fontSize: 25}}>{item.email}</Text>
            <Text style={{padding: 10,fontSize: 20}}>{item.name}</Text>
            </View>
            </TouchableNativeFeedback>

        : <TouchableNativeFeedback onPress={() => this.userSelected(item)}><Text style={{padding: 10,fontSize: 20}}>{item.email}</Text></TouchableNativeFeedback>
    }

    userSelected(item) {
        console.log(item)
        this.setState({selectedItem: item})
    }

    componentDidMount() {
      fetch("https://jsonplaceholder.typicode.com/users")
        .then(data => data.json())
        .then(response => this.setState({response}))
    }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>HI THERE</Text>
        {this.userListLayout()}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});
th3g3ntl3m3n
  • 151
  • 7
  • I've updated the code to reflect the changes you recommended. I can't get the onPress event to fire inside singleStore(item) because item.id never equals this.state.selectedItem.id. I consoledloged this.state.selectedItem and found out that it never reaches the onPress event and therefore the state for selectedItem never gets updated. Since I 'm imported a JSON file, can I set state for selectedItem in the constructor? – VK1 Feb 23 '18 at 08:07
  • You didn't added onPress in second tnf – th3g3ntl3m3n Feb 23 '18 at 08:23