Saving React State with JS-IPFS

Hi all,

Iā€™m playing around with JS-IPFS for the first time.

I was experimenting with whether or not I could save my react applications state to ipfs in the way I currently do to localstorage.

Hereā€™s what Iā€™ve tried (which is not working).

componentDidUpdate(){
   //here's how i current save state to localStorage
    localStorage.setItem("gobitsState", JSON.stringify(this.state))
  //here's how I was trying to repeat that for ipfs
    const node = new IPFS();
    node.once('ready', () => {
      console.log("ipfs node is ready");
    });
    const stateData = JSON.stringify(this.state);
    node.files.add(Buffer.from(stateData), (err, res) => {
    if (err || !res) {
      return console.error('ipfs add error', err, res)
    }
  })
}

Iā€™m still struggling with the js-ipfs documentation, so Iā€™m not sure if this is correct.

At present Iā€™m getting the following error:

index.js?0bef:64 Uncaught TypeError: Cannot read property 'put' of undefined
    at BlockService.put (index.js?0bef:64)
    at waterfall (index.js?8d96:400)
    at nextTask (waterfall.js?f8db:16)
    at next (waterfall.js?f8db:23)
    at eval (onlyOnce.js?425d:12)
    at Object.serialize (util.js?3584:34)
    at waterfall (index.js?8d96:399)
    at nextTask (waterfall.js?f8db:16)
    at exports.default (waterfall.js?f8db:26)
    at IPLDResolver._put (index.js?8d96:398)

The error in index.js64 is:

this._repo.blocks.put(block, callback)

Aside question, do I need to make sure to ā€œendā€ the node connection once iā€™ve saved the state? How do I do that.

Any advice to point me in the right direction is much appreciated.

Youā€™re adding the file before your node is ready to handle it. You need to have the node.files.add instruction within node.once('ready'). Your example should change to be like this:

    node.once('ready', () => {
        console.log("ipfs node is ready");
        const stateData = JSON.stringify(this.state);
        node.files.add(Buffer.from(stateData), (err, res) => {
            if (err || !res) {
                return console.error('ipfs add error', err, res)
            }
        })
    });

Also, keep in mind that componentDidUpdate runs everytime your state or props are changing and youā€™re creating a new IPFS node every time that happens. Instead, start the node at componentDidMount and add the node to this.state. That way, when itā€™s updating, you can just do this.state.node.files.add() instead.

Awesome. Thanks.

But even after setting this.state.node to new IPFS(), I"m still going to need to run node.once etc in the componentDidUpdate function right?

Second, I got it to work and I logged the console of res which gave me QmPpK6SKza2iz6qA4cm3uZ56Jf4YDSfA5guGBtgZGuwRVa.

which is great, but this is the hash for true. (see https://gateway.ipfs.io/ipfs/QmPpK6SKza2iz6qA4cm3uZ56Jf4YDSfA5guGBtgZGuwRVa)

I was expecting this to be the hash of the stringifyed state.

(FYI, Iā€™m pretty sure I donā€™t understand what Buffer is doing. )

But my hope is that at the end of the node.files.add() function, Iā€™ll have the hash for the stringifyed state.

Thanks so much for your help.