3

I'm writing a webapp using React and Redux. I have a Redux action that uses XMLHttpRequest to populate my reducer with data (in array format) from a REST API. I call the action in componentDidMount because thats what the React documentation says is best. When I try to access them in my render function I get a "array[0] is undefined message in the console." But the funny thing is if I define a function that returns JSX using array.map() then it works fine. It just doesn't let me access them individually. Does anyone know why that is?

Code:

import React from 'react'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import {Row, Col, Grid} from 'react-bootstrap'
import {fetchData} from '../actions'

class DataContainer extends React.Component {

  listData(array){
    return array.map((element) => {
      return(
        <Col lg = {3} md = {4} sm = {6} key = {element.id}>
          <h3>{element.name}</h3>
          <p>{element.description}</p>
        </Col>
      );
    });
  }

  componentDidMount(){
    this.props.getData() //call API
  }

  render () {
      return(
        <Grid>
          <Row componentClass = "section" id = "non-profits">
            {listData(props.data)} //this works
            {props.data[0].name} //this doesn't work
          </Row>
        </Grid>
      );

  }
}

function mapStateToProps(state){
  return{ //maps reducer state to props for use in component
    data: state.data //state.data stores the data from the REST API
  };
}

function mapDispatchToProps(dispatch){
  return bindActionCreators({getdata: fetchdata}, dispatch)//fetchData is the redux action that
                                                          //calls the REST API

}

export default connect(mapStateToProps, mapDispatchToProps)(DataContainer);
3
  • What does your initial data state look like? Commented Jan 8, 2017 at 22:15
  • The first time your component mounts, the data won't exist. Javascript is asynchronous, your component will mount (it's the "DID MOUNT" callback) before you even make the ajax call. You're trying to look up a prop before it's set. You need to handle that case in your render fn Commented Jan 9, 2017 at 0:26
  • I get that, but if the data doesn't exist then why does array.map work? It seems like if the data doesn't exist then shouldn't it also be undefined when I pass it into the list function? And the initial data state is just an empty array Commented Jan 10, 2017 at 0:42

1 Answer 1

3

Try this:

render () {
           return(
             <Grid>
               <Row componentClass = "section" id = "non-profits">
                  {(props && props.data && props.data.length > 0)} ? {props.data[0].name} : <span>None</span> //This should work
               </Row>
             </Grid>
           );
      }

I did not test this code. But this should work.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, that did work. I had tried testing for props and props.data before but testing that props.data.length > 0 turned out to be the condition that made it work. I'm still curious about array.map() though if anyone has an answer
When the app initializes the data array is empty. Therefore, its still "loopable" so the array map will work. props.data[0] access the first element in the array but if the array is empty on application load it will error because you're accessing something that does not exist. Also, you can still loop through an empty array using a for statement as well as long as the array is defined.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.