Search code examples
javascriptreactjsdexie

React query a db on component mount?


For this example I am using React with Dexie.js. I have a code, zanzibar, that, when run, adds a list of objects from my IndexDB to the page. I have two current things I would like to add to this.

First, there appears to be an issue with finding the ID of my database. For instance, when I run console.log(amigo.id) under my peaches function, it returns undefined. I also do not see an ID on my indexDB panel.

Second, now that I am able to run this from a click function, I would also like to load my indexDB data via componentDidMount. The purpose of this would be to load everything on my indexDB to my page on page load. My peaches function is supposed to do this, though I am not quite sure how to follow through.

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

peaches:function(){
    var datastoring = new Dexie('MySpace');
    datastoring.version(1).stores({
      friends: '++id, name, age'
    });

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

datastoring.friends.each((amigo)=>{
console.log(amigo.id+", "+amigo.name);

}); 

},  

componentDidMount:function(){
return this.peaches();
},

  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: '++id, name, age'
    });

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

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

    datastoring.friends.add(newFriend).then((id) => {
      // this is how you update the state of the object with new data
        var newResults = this.state.results.concat([Object.assign({}, newFriend, { id })]);
            this.setState({results: newResults});
    });
  },

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

  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}/>
        <ul>{this.renderResults(this.state.results)}</ul>
      </div>
    );
  }

});

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

Included in JSFiddle https://jsfiddle.net/jgwhxuam/


Solution

  • I am not familiar with Dexie.js, but I think I managed to get what you are asking for accomplished.

    Updated Fiddle: https://jsfiddle.net/jgwhxuam/2/

    First, I moved this block to the top so that you are not repeating yourself ("DRY").

    var datastoring = new Dexie('MySpace');
    datastoring.version(1).stores({friends: '++id, name, age'});
    datastoring.open().catch(function(err){ alert('Oh no son:' +err) });    
    

    Then, I tweaked your getInitialState results to an empty array so that it doesn't render some blank spaces on the dom (with bullets, etc).

    Instead of console logging the result in the peaches function, I used it to take your stored indexedDB data and input it into the state. I added a .then() to accomplish this. When the componentDidMount() runs, it should render the list as a result.

    The zanzibar function I just consolidated slightly and use the peaches function to update the state.

    The renderResults function I moved down into the render function. Not necessary, but helped me debug.

    If you have any questions, I can revise this answer. Good luck!