Jason Chen Jason Chen - 4 months ago 31
React JSX Question

Reactjs loop from a database

I would like to understand how to loop through an array from a database using ReactJS. For this particular instance I am using an IndexDB wrapper called dexie.js.

My React code is below. What I would like it to do is fill out

{this.state.results.name}
with the entire array of stuff that I add to it once I fill out the two boxes and click the submit button.

As is, the code adds the values to the database. I am just having trouble understanding how to use React to query them.

var SisterChristian = React.createClass({
getInitialState:function(){
return {results:[{name:'', age:''}]}
},

zanzibar:function(){
var resname = document.getElementById('inputname').value;
var resage = document.getElementById('inputage').value;
var datastoring = new Dexie('MySpace');
datastoring.version(1).stores({
friends: 'name, age'
});

datastoring.open().catch(function(err){
alert('Oh no son:' +err);
});

datastoring.friends.each((friend)=>{
this.setState({results:[{name:resname, age:resage}] });
});

datastoring.friends.add({
name: resname,
age: resage
});
},
render:function(){
return (<div>
<input type="text" id="inputname" />
<input type="text" id="inputage" />
<input type="submit" value="Shipping And Handling" onClick={this.zanzibar}/>
<p>{this.state.results.name}</p>
</div>);}

});

ReactDOM.render(<SisterChristian/>, document.getElementById('bacon'));


You can also see it on CodePen, which will hopefully make it easier to see.
http://codepen.io/jasonchenthrow/pen/GqXoyr

Answer

I think you're getting mixed up as to what's an array and what's a single object. Here's some general tips.

  • indent!!
  • To loop over an array and output DOM, use the array method map and for item in the array return the required DOM. It's handy (but not necessary) to have a separate function - this keeps your DOM tree inside render() easy to read.
  • In your example you're saving data to state and Dexie, so you must save your new data to state and Dexie. When your app gets more complicated you should save your data to a central store, and pass that store into the component as props.
  • If you're typing code that looks up something in the DOM and returns it (e.g. querySelector) you're probably thinking the wrong way around. This is brittle (you have to have an ID and know that the ID is unique across your entire app) and also this is what refs are for.

Here's the result:

var SisterChristian = React.createClass({
  getInitialState:function(){
    return {results:[
      {
        name:'Jason',
        age:'25'
      },
      {
        name:'Bob',
        age:'29'
      }
    ]}
  },

  zanzibar:function(){
    // don't use document.querySelector(), you should be able to access any of your DOM elements like this
    var resname = this.inputNameEl.value;
    var resage = this.inputAgeEl.value;
    var datastoring = new Dexie('MySpace');
    datastoring.version(1).stores({
      friends: 'name, age'
    });

    datastoring.open().catch(function(err){
      alert('Oh no son:' +err);
    });

    // you can't do this, you need to add a new item to the results array, not reset the array
    // datastoring.friends.each((friend)=>{
    //   this.setState({results:[{name:resname, age:resage}] });
    // }); 

    var newFriend = {
      name: resname, 
      age: resage
    };

    datastoring.friends.add(newFriend);

    // this is how you update the state of the object with new data
    var newResults = this.state.results.slice(); // clone the array
    newResults.push(newFriend);
    this.setState({results: newResults});
  },

  renderResults:function(results) {
    return results.map(result => { // this is how you create DOM elements from an array of objects
      return <p key={result.name}>{result.name}, {result.age}</p>;
    });
  },

  render:function(){
    return (
      <div>
        <input type="text" id="inputname" ref={el => this.inputNameEl = el} />
        <input type="text" id="inputage" ref={el => this.inputAgeEl = el} />
        <input type="submit" value="Shipping And Handling" onClick={this.zanzibar}/>
        <p>{this.state.results.name}</p>
        <p>{this.renderResults(this.state.results)}</p>
      </div>
    );
  }

});

ReactDOM.render(<SisterChristian/>, document.getElementById('bacon'));