Search code examples
javascriptattributesreactjsweb-component

Components with default property sets


I'm looking for a way to set the default properties of a react component with one property. Rather then being repetitive every time I utilize a function with the same attributes. I'd like a way to reuse that component with those attributes without having to make it into it's own component.

Here's an example, even though there's only one property in each set. Imagine I have a couple of different presets each having 10 props / attributes each, it's way easier to call just one attribute and have all of them be filled in for you.

var List = React.createClass({
  getDefaultProps: function(){
    var propSets = {
      "default":{
        "icon": "fa fa-wifi"
      },
      "fruits":{
        "icon": "fa fa-apple"
      },
      "vegetables":{
        "icon": "fa fa-tree"

      }
    }
    //setPropsViaProp
    if(typeof this.props.set === "undefined") return propSets["default"];
    return propSets[this.props.set];
  },
  render: function() {
    return (
      <div className="list">
        <i class="{ this.props.icon }"></i>
      </div>
    )
  }
});

<List set="fruits">
<List set="vegetables">

This is throwing

Cannot read property 'set' of undefined

I'm guessing props isn't defined yet within getDefaultProps()


Solution

  • It is too late to modify the props of a component by the time you know what the set property will be.

    You could instead use a mixin that installs a method of getting these properties:

    var PropSetsMixin = {
        getProp: function(name) {
            // Simplified implementation for the answer, use better one in production
            return this.propSets[this.props.set][name];
        }
    };
    
    
    var List = React.createClass({
        mixins: [PropSetsMixin],
    
        propSets: {
            "default":{
                "icon": "fa fa-wifi"
            },
            "fruits":{
                "icon": "fa fa-apple"
            },
            "vegetables":{
                "icon": "fa fa-tree"
            }
        },
    
        render: function() {
            return (
                <div className="list">
                    <i className={this.getProp("icon")}></i>
                </div>
            )
        }
    });
    

    Or if you don't like function call:

    var PropSetsMixin = {
        componentWillReceiveProps: function(props) {
            this._applyPropSets(props);
        },
    
        componentWillMount: function() {
            this._applyPropSets(this.props);
        },
    
        _applyPropSets: function(props) {
            var set = props.set || "default";
            this.propSet = this.propSets[set];
        }
    };
    
    
    var List = React.createClass({
        mixins: [PropSetsMixin],
    
        propSets: {
            "default":{
                "icon": "fa fa-wifi"
            },
            "fruits":{
                "icon": "fa fa-apple"
            },
            "vegetables":{
                "icon": "fa fa-tree"
            }
        },
    
        render: function() {
            return (
                <div className="list">
                    <i className={this.propSet.icon}></i>
                </div>
            )
        }
    });