Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create new elements with React mapping props

Tags:

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?

like image 879
Brian Chan Avatar asked Aug 10 '16 01:08

Brian Chan


1 Answers

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>
        )
    }

})
like image 176
Ori Drori Avatar answered Sep 24 '22 16:09

Ori Drori