Reusing properties within map loop in ReactJS - best practice

- 1 answer

Ad

I am trying to figure out the best way to render two blocks of code in ReactJS, one will be used for desktop and the other for mobile. Functionality wise they will do exactly the same thing but have different markup wrapped around them, an example would be a carousel that renders differently on mobile.

I am using the map function to iterate over the object properties, I have working code below but I am duplicating variables and reassigning the same values which is obviously inefficient as I am doing this for each code block.

Can anyone suggest a nice / best practice way of doing what I need?

Sorry for the basic question!

render: function() {
return (
    <div>
        <div className="hidden-xs">
            {
                this.state.userItems.map(function (item) {

                    var someValue = 'value' in item ? item.value : '';
                    var anotherValue = 'anotherValue' in item ? item.anotherValue : '';

                    return (
                        <div key={someValue}>
                            {someValue}<br>{anotherValue}
                        </div>
                    )
                })
            }
        </div>
        <div className="visible-xs">
            {
                this.state.userItems.map(function (item) {

                    var someValue = 'value' in item ? item.value : '';
                    var anotherValue = 'anotherValue' in item ? item.anotherValue : '';

                    return (
                        <div key={someValue}>
                            <div className="differentMarkup">
                              {someValue}<br>{anotherValue}
                            </div>
                        </div>
                    )
                })
            }
        </div>
    </div>
)}
Ad

Answer

Ad

Updated answer:

If the inner items can have different markup, I would say it depends how different their markup is going to be. For example, you could have two separate methods that prepare the markup of the mobile and non-mobile version of the items separately. Something like this:

renderUserItem: function(itemData) {
    return (
        <div key={itemData.someValue}>
            {itemData.someValue}<br>{itemData.anotherValue}
        </div>
    )
},

renderMobileUserItem: function(itemData) {
    return (
        <div key={itemData.someValue}>
            <div className="differentMarkup">
                {itemData.someValue}<br>{itemData.anotherValue}
            </div>
        </div>
    )
},

prepareItemData: function(item) {
    return {
        someValue: item.value ? item.value : '';
        anotherValue: item.anotherValue ? item.anotherValue : '';
    };
},

render: function() {
    // Prepare the variables you will need only once
    let parsedUserItems = this.state.userItems.map(this.prepareItemData);

    return (
        <div>
            <div className="hidden-xs">
                { parsedUserItems.map(this.renderUserItem) }
            </div>
            <div className="visible-xs">
                { parsedUserItems.map(this.renderMobileUserItem) }
            </div>
        </div>
    )
}

You could also have a single method if the differences between mobile and non-mobile are not too big. For example, using ES6 arrow functions:

renderUserItem: function(itemData, renderWrapper) {
    return (
        <div key={itemData.someValue}>
            {renderWrapper ? <div className="differentMarkup"> : ''}
                {itemData.someValue}<br>{itemData.anotherValue}
            {renderWrapper ? </div> : ''}
        </div>
    )
},

render: function() {
    // Prepare the variables you will need only once
    let parsedUserItems = this.state.userItems.map(this.prepareItemData);

    return (
        <div>
            <div className="hidden-xs">
                { parsedUserItems.map(item => this.renderUserItem(item, false)) }
            </div>
            <div className="visible-xs">
                { parsedUserItems.map(item => this.renderUserItem(item, true)) }
            </div>
        </div>
    )
}



Original answer below:

If I understood correctly and the inner items have the same markup, you could extract the function passed into map to a separate method:

renderUserItem: function(item) {
    var someValue = 'value' in item ? item.value : '';
    var anotherValue = 'anotherValue' in item ? item.anotherValue : '';

    return (
        <div key={someValue}>
            {someValue}<br>{anotherValue}
        </div>
    )
},

render: function() {
    return (
        <div>
            <div className="hidden-xs">
                { this.state.userItems.map(this.renderUserItem) }
            </div>
            <div className="visible-xs">
                { this.state.userItems.map(this.renderUserItem) }
            </div>
        </div>
    )
}
Ad
source: stackoverflow.com
Ad