Props is undefined, but I can see it console logging the prop

Viewed 1392

I'm new-ish to react, and I am trying to load more information into an array of records, only if the user starts scrolling down. The issue is that the new information appears in the array, but if you try to call it, it returns undefined. What am I not understanding here?

The Parent Component:

class ComplementSection extends Component {
  constructor(props) {
    super(props)

    this.state = {
      complements: '',
      updatingComplements: false
    }
    this.updateComplementsArray = this.updateComplementsArray.bind(this)
  }


  componentWillMount() {
    let complements = this.props.user.complements
    let groupComplements = this.props.user.groupComplements
    let allComplements = [...complements, ...groupComplements]
    allComplements.sort(function compare(a, b) {
      dateA = new Date(a.created_at)
      dateB = new Date(b.created_at)
      return dateB - dateA
    })
    this.setState({
      complements: allComplements
    })
  }

  updateComplementsArray() {
    this.state.complements.map((complement, index) => {
      let complements = this.state.complements
      if(complement.meeting_id) {
        meetingApiHelper.getMeeting(this.props.currentUser.authToken, complement.meeting_id)
        .then(results => {
          complements[index].meeting = results.data.data;
          this.setState({complements: complements});
        })
        .catch(err => {
          console.log(err.response)
        })
      }
    })
    this.setState({
      updatingComplements: true
    })
  }

  componentDidUpdate() {
    if(this.props.scrolling === true && this.state.updatingComplements === false) {
      this.updateComplementsArray()
    }
  }



  render() {
    if(this.props.scrolling === true && this.state.updatingComplements === true){
      return(
        <View>
            <Text style={profileStyles.yellowLobsterHeader}>Complements</Text>
            <FlatList
              data={this.state.complements}
              renderItem={({item}) => <ComplementItem key={item.id}  item={item} navigation={this.props.navigation}  />}
              keyExtractor={(item, index) => index}
            />
        </View>
      )
    } else {
      return null
    }
  }
}

export default ComplementSection

The Child Component:

class ComplementItem extends Component {
  constructor(props) {
     super(props)
  }

  componentDidMount() {
    console.log(this.props.item)
    console.log(this.props.item.meeting)
  }

  render() {
    return (
      <View style={formStyles.formStandard}>
          <Text style={profileStyles.profileBio}>Placeholder text</Text>
      </View>
    )
  }
}

export default ComplementItem;

In the componentDidMount function, this.props.item returns:

{created_at:"2017-11-08T22:11:27.272Z"
id:29
meeting:{id: 219, requestor_id: 441, requestee_id: 32, lang_one_id: 1, lang_two_id: 6, …}
meeting_id:219
notes:"Clex Sss was really nice and very easy to talk to. I look forward to meeting again!"
reviewee:32
reviewer:441
updated_at:"2017-11-08T22:11:27.272Z"}

but this.props.item.meeting returns undefined

What am I missing here??

1 Answers

There are two problems here

First

You shouldn't mutate the state

let complements = this.state.complements
complements[index].meeting = results.data.data; //... Here, you should either use a spread to shallow compare or use tradition JS fix JSON.parse(JSON.stringify(your_obj)) for a deep clone

Second

You need not update state on each map iteration once the api fetch succeeds which may cause of performance issue.

Therefore you can make use of the async/await in this case

updateComplementsArray = async () => {
    const updatedCompliments = await Promise.all(
      this.state.complements.map(async (complement, index) => {
        if(complement.meeting_id) {
          try {
            const meetingResults = await meetingApiHelper.getMeeting(this.props.currentUser.authToken, complement.meeting_id)
            complement.meeting = meetingResults.data.data;
          } catch(ex) {
            // handle the api exception here
          }
        }
        return complement // Map expects a return for each iteration. Return the updated complement object here
      })
    )
    // Once the Promises inside map finish executing, update the state
    this.setState({ complements: updatedCompliments });
  }
Related