ReactJS <List /> — Composition

Demonstrating a List View built in React, taking advantage of Composition to customize behavior of base List component.

by Jon Beebe

HTML

<script src="http://fb.me/JSXTransformer-0.10.0.js"></script>
<script src="http://fb.me/react-with-addons-0.10.0.js"></script>
<script src="http://fb.me/react-js-fiddle-integration.js"></script>

CSS

html, body {
    font-family: sans-serif;
    font-size: 16px;
}

ul, li {
    margin: 0;
    padding: 0;
}

ul li {
    list-style-type: none;
}

.mario-bros {
    color: red;
    text-shadow: 0 0 1px white,
        0 0 2px white,
        0 0 2px white,
        0 0 10px blue, 
        0 0 10px blue, 
        0 0 4px blue
}

JavaScript 1.7

/** @jsx React.DOM */
'use strict';

var ListItemContent = React.createClass({
    render: function () {
        return <div>
            <p>{this.props.text}</p>
        </div>;
    }
});

var ListItem = React.createClass({
    render: function () {
        return <li>
            <ListItemContent text={this.props.text} />
        </li>;
    }
});

var MarioItem = React.createClass({
    render: function () {
        return <li className="mario-bros">
            <ListItemContent text={this.props.text} />
        </li>;
    }
});

var List = React.createClass({

    getDefaultProps: function () {
        return {
            delegate: this
        };
    },
    
    render: function() {
        return <ul>
            {this.renderItems()}
        </ul>;
    },
    
    renderItems: function () {
        var delegate = this.props.delegate;
        var items = this.props.items;
        return items.map(delegate.getItemViewForItem);
    },
    
    // @ListDelegate
    
    getItemViewForItem: function (item) {
        return new ListItem({
            text: item
        });
    }
});

var CharacterList = React.createClass({

    getItemViewForItem: function (item) {
        var ItemClass = ListItem;
        if(item.toLowerCase().indexOf('mario') > -1) {
            ItemClass = MarioItem;
        }
        return new ItemClass({
            text: item
        });
    },
    
    render: function () {
        return <List delegate={this} items={this.props.items} />;
    }
    
});

var items = [
    'Frogger',
    'The Legend of Zelda',
    'Mario Bros.',
    'Metroid',
    'Donkey Kong',
    'Super Mario Bros.'
];

React.renderComponent(<CharacterList items={items} />, document.body);