lost9123193
lost9123193

Reputation: 11040

Calling A State Property in React/Redux

I have a redux store with a state called "Pets" which stores an array of the following:

[{"id"2,"name":"Cat"},
 {"id":3,"name":"Dog"},
 {"id":4,"name":"Fish"}
]

In my component, I map the states like this: (I'm using redux forms and react-bootstrap-table)

class PetsPage extends Component {
    constructor(props) {
      super(props);
      this.state =({
        selected:[]
      });
    this.showRow = this.showRow.bind(this);
  }

  componentWillMount() {
    this.props.fetchPets();
  }


render() {
  const {
    handleSubmit,
    previousPage,
    pets
  } = this.props


  if (!pets){
    return (
      <div className="container">
          <div> Loading...</div>
      </div>
    );
  }

  return (  
      <div className="container">

       <BootstrapTable 
          data={pets} 
          search={true} 
          striped={true}
          hover={true}
          condensed={true}
          selectRow={selectRowProp}>
          <TableHeaderColumn dataField="id" isKey={true}>Pet #</TableHeaderColumn>
          <TableHeaderColumn dataField="name">Company</TableHeaderColumn>
        </BootstrapTable>

          <p> Currently Chosen: <span>  id: {this.state.selected}</span> </p>

          <div className="btn-group">
            <button type="button" onClick={previousPage}  className="btn btn-success btn-lg"><i/> Previous</button>
            <button type="submit" className="btn btn-success btn-lg">Next</button>
        </div>
      </div>
    </form>
    )
  }
}


function mapStateToProps(state) {
  return { pets: state.pets.all };
}

export default reduxForm({
  form: 'wizard',              
  fields,                      
  destroyOnUnmount: false,    
  validate                    
}, mapStateToProps, actions)(PetsPage)

So far, everything WORKS. My problem arises when I call the pets prop like this:

<p> Currently Chosen: {pets[2].name}</p>

I keep getting this error:

TypeError: pets[2] is undefined

Ideally I want to be able to call the name of the pet by the ID which is provided by the "selected" state.

EDIT --- I noticed the code actually WORKS if I were to go to another page and come back to this page. This is kind of confusing because I thought having the ...loading container would prevent this from happening.

Upvotes: 2

Views: 180

Answers (3)

lost9123193
lost9123193

Reputation: 11040

Ok, I just figured it out. Following xiaofan2406's suggestion, I literally have to put

if(this.props.pets[0])

Because

if(this.props.pets)

will always be true.

Upvotes: 0

xiaofan2406
xiaofan2406

Reputation: 3310

How do you obtain the initial state of pets? were those retrieved asynchronously? (which i suspect it is)

When your BootstrapTable initially load, the async call was not complete, pets was still undefined, hence the error. Then when you go to another page, and come back to this page, your async call was finished, pets is now an array, and it works.

If I am right so far, add something like this in your BootstrapTable:

if(this.props.pets) {
   <p> Currently Chosen: {pets[2].name}</p>
   ... // render your pets props within the 
} else {
   // render some loading indicator
}

Edit: if your pets was initialized as an empty array, check the length of the pets instead of the truthy value

Upvotes: 2

ceckenrode
ceckenrode

Reputation: 4713

Shouldn't you be doing this.props.pets[2] ? Or this.state.pets[2] ? Unsure exactly what's happening but I don't think pets[2] on it's own would ever be anything. If that doesn't help can you post some more of your code?

Upvotes: 0

Related Questions