Brian Chan Brian Chan - 3 months ago 8
Javascript Question

How to create new elements with React mapping props

I am trying to create elements with React dynamically but I can't seem to use

this.props
correctly it seems. What I currently have does not produce any new elements. I've tried looking at various other answers and mimicking them but without any luck.

React.createClass({
getDefaultProps: function() {
var items = [];
chrome.storage.local.get(null, function(result) {
var keys = Object.keys(result);
// get all the keys from chrome storage and add to array items
for (var i = 0; i < keys.length; i++) {
items.push(keys[i]);
}
})
return {
items: items
}
},
render: function() {
// display an element with name of key
return (
<div>
{this.props.items.map(function loop(item, i) {
return (<div>{item}</div>)
})}
</div>
)
}
})


However when I substitute a literal array for
this.props.items
, I get new elements. Any ideas what I'm missing here?

Answer

chrome.storage is asynchronous:

It's asynchronous with bulk read and write operations, and therefore faster than the blocking and serial localStorage API.

This means that the getDefaultProps finishes before the call comes back, and the initial state is { items: [] }. To fix that, make the request to the storage in 'componentDidMount', and set the state when the data arrives:

React.createClass({

    getDefaultProps: function() {
        return {
            items: [] // initial is empty
        }
    },

    componentDidMount: function() { // the component has be rendered for the 1st time
        chrome.storage.local.get(null, function(result) { // receive the items
            var keys = Object.keys(result);
            // get all the keys from chrome storage and add to array items
            for (var i = 0; i < keys.length; i++) {
                items.push(keys[i]);
            }

            this.setState({ items: items }); // set the state
        }.bind(this)) // bind the callback to the component's this, so you can use this.setState
    },

    render: function() {
        // display an element with name of key
        return (
            <div>
            {this.props.items.map(function loop(item, i) {
                return (<div>{item}</div>)
            })}
            </div>
        )
    }

})
Comments