59

I'm trying to iterate through all the keys in a hash, but no output is returned from the loop. console.log() outputs as expected. Any idea why the JSX isn't returned and outputted correct?

var DynamicForm = React.createClass({
  getInitialState: function() {
    var items = {};
    items[1] = { name: '', populate_at: '', same_as: '', 
                 autocomplete_from: '', title: '' };
    items[2] = { name: '', populate_at: '', same_as: '', 
                 autocomplete_from: '', title: '' };
    return {  items  };
  },



  render: function() {
    return (
      <div>
      // {this.state.items.map(function(object, i){
      //  ^ This worked previously when items was an array.
        { Object.keys(this.state.items).forEach(function (key) {
          console.log('key: ', key);  // Returns key: 1 and key: 2
          return (
            <div>
              <FieldName/>
              <PopulateAtCheckboxes populate_at={data.populate_at} />
            </div>
            );
        }, this)}
        <button onClick={this.newFieldEntry}>Create a new field</button>
        <button onClick={this.saveAndContinue}>Save and Continue</button>
      </div>
    );
  }
martins
  • 9,669
  • 11
  • 57
  • 85

2 Answers2

121
Object.keys(this.state.items).forEach(function (key) {

Array.prototype.forEach() doesn't return anything - use .map() instead:

Object.keys(this.state.items).map(function (key) {
  var item = this.state.items[key]
  // ...
Jonny Buchanan
  • 61,926
  • 17
  • 143
  • 150
  • Yeah, I replaced `forEach` with `map` and it worked. Thanks! :-) – martins Apr 09 '15 at 09:42
  • 1
    var item = this.state.item[key]. this is not like what you thought, need to use var that = this, and that.state.item[key] – xiongjiabin Oct 07 '15 at 11:29
  • `this` is being passed as the second argument, which sets the appropriate value of `this` when the function is called. – Jonny Buchanan Oct 07 '15 at 17:37
  • 7
    if your object refers to a prop which is 'undefined' or 'null' at the **first render**, you will get an **error**. Using "Object.keys(this.props.items **|| {}**).map(...)" resolves it. – Made in Moon Mar 15 '16 at 19:29
  • Wow! Thanks @MadeInMoon, I had no idea how to resolve this in my mapStateToProps when it was throwing a error 'null is not an object (evaluating 'Object.keys' Thanks again :) – Michael Mar 31 '17 at 01:18
5

a shortcut would be:

Object.values(this.state.items).map({
  name,
  populate_at,
  same_as,
  autocomplete_from,
  title
} => <div key={name}>
        <FieldName/>
        <PopulateAtCheckboxes populate_at={data.populate_at} />
     </div>);
Olivier Pichou
  • 157
  • 1
  • 6