I have a promise chain that creates an array. At the end of the chain, I want to copy that array to one of my state variables. However, I get "Objects are not valid as a React child"
I've tried various ways to chain the promise so that the state variable captures the array I want to put in it. If I put setState at the end of my function, it misses what I try to capture in the promise chain
addIPFSItem = () => {
var finalItems = []
var searchAddress = "0x9Cf0dc46F259542A966032c01DD30B8D1c310e05";
const contract = require('truffle-contract')
const simpleStorage = contract(SimpleStorageContract)
simpleStorage.setProvider(this.state.web3.currentProvider)
this.state.web3.eth.getAccounts((error, accounts) => {
simpleStorage.deployed().then((instance) => {
this.simpleStorageInstance = instance
return this.simpleStorageInstance.getLength(searchAddress);
}).then((accountLength) => {
var movieItems = []
var i;
//WITHIN THIS LOOP extend the chain to add to movies
for (i = 0; i < accountLength; i++) {
var p = this.simpleStorageInstance.getBook(searchAddress, i, { from: searchAddress }).then((hashVal) => {
return hashVal;
})
movieItems.push(p)
}
//return items
return movieItems
}).then((temp) =>{
var i;
var indexCounter=0;
var arrayLength;
arrayLength=temp.length
for(i=0; i<arrayLength; i++){
var p = temp[i].then((temp)=>{
var ipfsPrefix = "https://ipfs.io/ipfs/";
var ipfsURL = ipfsPrefix + temp;
var movieItem = {id: indexCounter, poster_src: ipfsURL, title: "Some Title", overview: "blah blah"}
indexCounter++
return movieItem;
}).then((item)=>{
finalItems.push(item)
}).then(()=>{
if(finalItems.length == arrayLength ){
//*******************************
//Here is where I try to set state and get the error
//*******************************
this.setState({rows: finalItems})
}
})
}
return
})
})
}
I expect my row
in my state to change, but I get Objects are not valid as a React child
UPDATE: here is my render() function
render() {
//Shows customer their account
var userAccount = "Your account is: " + this.state.account;
//Shows current IPFS _address
var currIPFS = "The IPFS address is: " + this.state.ipfsHash;
return (
<div className="App">
<table className="titleBar">
<tbody>
<h1>Interactive News</h1>
</tbody>
</table>
<input style={{
fontSize: 14,
display: 'block',
paddingTop: 8,
paddingBottom: 8,
paddingLeft: 14,
width: "99%"
}} onChange={this.searchChangeHandler} placeholder="Enter address for item lookup" />
{this.state.rows}
<main className="container">
<div className="pure-g">
<div className="pure-u-1-1">
<h1>Your Image</h1>
<p>This image is stored on IPFS & The Ethereum Blockchain!!!</p>
<br />
<font size="5">
<span className="badge badge-info" dangerouslySetInnerHTML={{__html: userAccount}} />
<br />
<br />
<span className="badge badge-light" dangerouslySetInnerHTML={{__html: currIPFS}} />
<br />
</font>
<br />
<br />
<button onClick={this.addIPFSItem}
className="btn btn-info btn-sm m-1">ShowList</button>
<br />
<br />
<button onClick={this.handleFirst}
className="btn btn-info btn-sm m-1">First</button>
<button onClick={this.handleDecrement}
className="btn btn-primary btn-sm m-1"> Prev </button>
<font size="5">
<span className="badge badge-success">
{this.state.index}
</span>
</font>
<button onClick={this.handleIncrement}
className="btn btn-primary btn-sm m-1">Next</button>
<button onClick={this.handleLast}
className="btn btn-info btn-sm m-1">Last</button>
<br/>
<img src={`https://ipfs.io/ipfs/${this.state.ipfsHash}`} alt=""/>
<h2>Upload Image</h2>
<form onSubmit={this.onSubmit} >
<input type='file' onChange={this.captureFile} />
<input type='submit' />
</form>
</div>
</div>
</main>
</div>
);
}
I'm not sure if my render() function is okay. Note that when I press the button <button onClick={this.addIPFSItem} className="btn btn-info btn-sm m-1">ShowList</button>
, that calls the addIPFSItem()
function. I don't know if I need a componentDidMount()
as it happens after the initial rendering.
React cannot render objects directly. You need to return it as react DOM components. Since 'this.state.rows' is an array of object you need to loop through it and wrap each object inside a meaningful DOM component eg. li or div ..
<ul>
{
this.state.rows.map((row, index) => {
return (
<li key={index}>{row.title}</li>
)
})
}
</ul>
<main className="container">
<div className="pure-g">