javascript - PropTypes of specific component? - Stack Overflow

admin2025-04-21  0

I've got this simple React ponent:

import {PropTypes} from 'react';
import Column from './Column';

export default function ColumnContainer({children}) {
    return (
        <div className="cr-column-container">{children}</div>
    );
}

let ColumnType = PropTypes.instanceOf(Column);

ColumnContainer.propTypes = {
    children: PropTypes.oneOfType([
        ColumnType,
        PropTypes.arrayOf(ColumnType),
    ]).isRequired,
};

Which I use like this:

render() {
    return (
        <ColumnContainer>
            <Column>
                *snip*
            </Column>
        </ColumnContainer>
    );
}

But it's failing prop-type validation:

Warning: Failed prop type: Invalid prop `children` supplied to `ColumnContainer`.
    in ColumnContainer (created by ExampleContainer)
    in ExampleContainer

Why is that? I've only used Columns inside of the ColumnContainer. Does PropTypes.instanceOf(Column) not work like I expect? How am I supposed to specify that ColumnContainer will only accept children of type Column?

I've got this simple React ponent:

import {PropTypes} from 'react';
import Column from './Column';

export default function ColumnContainer({children}) {
    return (
        <div className="cr-column-container">{children}</div>
    );
}

let ColumnType = PropTypes.instanceOf(Column);

ColumnContainer.propTypes = {
    children: PropTypes.oneOfType([
        ColumnType,
        PropTypes.arrayOf(ColumnType),
    ]).isRequired,
};

Which I use like this:

render() {
    return (
        <ColumnContainer>
            <Column>
                *snip*
            </Column>
        </ColumnContainer>
    );
}

But it's failing prop-type validation:

Warning: Failed prop type: Invalid prop `children` supplied to `ColumnContainer`.
    in ColumnContainer (created by ExampleContainer)
    in ExampleContainer

Why is that? I've only used Columns inside of the ColumnContainer. Does PropTypes.instanceOf(Column) not work like I expect? How am I supposed to specify that ColumnContainer will only accept children of type Column?

Share Improve this question asked Sep 12, 2016 at 18:54 mpenmpen 284k281 gold badges892 silver badges1.3k bronze badges 2
  • check this out: github./facebook/react/issues/2979 – james emanon Commented Sep 12, 2016 at 19:30
  • @jamesemanon Just found that. None of the solutions presented are ideal though. – mpen Commented Sep 12, 2016 at 19:41
Add a ment  | 

2 Answers 2

Reset to default 5

Did some digging, came up with this helper function based on josephmartin09's solution:

export function childrenOf(...types) {
    let fieldType = PropTypes.shape({
        type: PropTypes.oneOf(types),
    });

    return PropTypes.oneOfType([
        fieldType,
        PropTypes.arrayOf(fieldType),
    ]);
}

Usage:

ColumnContainer.propTypes = {
    children: childrenOf(Column).isRequired,
};

It's not ideal because it doesn't support native DOM elements like 'div' and the error message is worthless, but it'll do for now.

I overhauled childrenOf with support for react-hot-loader 4.x:

import { areComponentsEqual } from 'react-hot-loader';

export function childrenOf(...types) {
    return requirable((props, propName, ponentName, location, propFullName) => {
        const ponent = props[propName];
        if(!location) {
            location = 'prop';
        }
        if(!propFullName) {
            propFullName = propName;
        }
        const check = c => types.some(type => areComponentsEqual(type,c.type));
        const valid = Array.isArray(ponent) ? ponent.every(check) : check(ponent);
        if(!valid) {
            return new Error(
                `Invalid ${location} \`${propFullName}\` supplied to \`${ponentName}\`. Every element must be a <${types.map(t => getDisplayName(t)).join('|')}>.`
            );
        }
        return null;
    });
}

function requirable(predicate) {
    const propType = (props, propName, ...rest) => {
        // don't do any validation if empty
        if(props[propName] === undefined) {
            return null;
        }

        return predicate(props, propName, ...rest);
    };

    propType.isRequired = (props, propName, ponentName, ...rest) => {
        // warn if empty
        if(props[propName] === undefined) {
            return new Error(`Required prop \`${propName}\` was not specified in \`${ponentName}\`.`);
        }

        return predicate(props, propName, ponentName, ...rest);
    };

    return propType;
}

Usage example:

export function TBody({children, ...attrs}) {
    return <tbody {...attrs}>{children}</tbody>;
}

TBody.propTypes = {
    children: WxTypes.childrenOf(TRow),
};
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745242106a292073.html

最新回复(0)