State does not change until the second button press? Adding a call back throws an error “invariant violation: invalid argument passed”

跟風遠走 提交于 2019-12-13 03:55:01

问题


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>
        )
    }
}

回答1:


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,
  },
});


来源:https://stackoverflow.com/questions/48925487/state-does-not-change-until-the-second-button-press-adding-a-call-back-throws-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!