Skip to content Skip to sidebar Skip to footer

Can A React Prop Type Be Defined Recursively?

Suppose we're defining a React class that will display a tree. React.createClass({ propTypes: { tree: treeType }, render: function () { // ... } });

Solution 1:

A React prop type is just a function, so it can be referenced lazily like this:

functionlazyFunction(f) {
    returnfunction () {
        return f.apply(this, arguments);
    };
}

var lazyTreeType = lazyFunction(function () { 
    return treeType;
});

var treeType = React.PropTypes.shape({
    value: React.PropTypes.string.isRequired,
    children: React.PropTypes.arrayOf(lazyTreeType)
})

The rest of the code for a complete working example (also available as a jsfiddle):

functionhasChildren(tree) {
    return !!(tree.children && tree.children.length);
}

varTree = React.createClass({
    propTypes: {
        tree: treeType
    },
    render: function () {
        returnthis.renderForest([this.props.tree], '');
    },
    renderTree: function (tree, key) {
        return<liclassName="tree"key={key}><divtitle={key}>{tree.value}</div>
            {hasChildren(tree) &&
                this.renderForest(tree.children, key)}
        </li>;
    },
    renderForest: function (trees, key) {
        return<ol>{trees.map(function (tree) {
            return this.renderTree(tree, key + ' | ' + tree.value);
        }.bind(this))}</ol>;
    }
});

var treeOfLife = { value: "Life", children: [
    {value: "Animal", children: [
        {value: "Dog"},
        {value: "Cat"}
    ]},
    {value: "Plant"}
]};

React.render(
    <Treetree={treeOfLife}/>,
    document.getElementById('tree'));

Screenshot of the result:

Screenshot of the result

Solution 2:

Here's another approach, courtesy of jethrolarson on GitHub:

Given the recursive component Tree

importReactfrom'react';

constTree = ({treeData}) => (
    <div>
        {treeData.nodeName}{' '}
        {treeData.children.map(subTree => (
            <TreetreeData={subTree} />
        ))}
    </div>
);

that takes a tree data structure like the one below

                Root
                /  \
           Child1   Child2
          /     \        \
     GChild1   GChild2   GChild3

(as code:

consttreeData= {
    nodeName:"Root",
    children: [
        {
            nodeName:"Child1",
            children: [
                {nodeName:"GChild1"},
                {nodeName:"GChild2"},
            ]
        },
        {
            nodeName:"Child2",
            children: [
                {nodeName:"GChild3"},
            ]
        },
    ]
};

),

the propTypes for Tree can be defined as:

import PropTypes from'prop-types';

const treeDataShape = {
    nodeName: PropTypes.string.isRequired,
};
treeDataShape.children = PropTypes.arrayOf(PropTypes.shape(treeDataShape));

Tree.propTypes = {
    treeData: PropTypes.shape(treeDataShape),
};

Note how all of the references to treeDataShape refer to the same object. Defining children after the object is created lets you recursively reference the same object.

Solution 3:

I created recursive prop types something like this and it worked for me. Let me know if it works for you as well. lazyTreeType function will be called as many times as there is a sub in the object.

const lazyTreeType = () => some_props;
const some_props= PropTypes.shape({
  date: PropTypes.string,
  updated: PropTypes.string,
  name: PropTypes.string,
  sub: PropTypes.arrayOf(lazyTreeType),
  type: PropTypes.string,
});

const component_proptype = PropTypes.shape({
  id: PropTypes.string,
  sub: PropTypes.arrayOf(some_props),
});

Post a Comment for "Can A React Prop Type Be Defined Recursively?"