1

Been banging my head against the wall on this one. I have a component I use for language translations, that is connected to my redux store, where language values are kept. It gets provided a language key and renders blurred placeholder text until the language values are put into state, in which case it renders the requested strings. I am trying to enforce this as the only prop type for props of several components. But I keep seeing errors.

import React from "react";
import PropTypes from 'prop-types';
import { connect } from "react-redux";
import { dummyText } from "../../constants/placeholderDummyText";
import { substrByWordCount } from "../../utilities/strings";

// displays blurred dummy text if placeholder is supplied, else displays the language value for the key provided
export const TextValue = ({ language, langKey, placeholderWordCount = 1 }) => {

    const hasLanguageAvailable = Object.entries(language).length !== 0;

    const placeholder = substrByWordCount(dummyText, placeholderWordCount);

    return hasLanguageAvailable ? (
        <span dangerouslySetInnerHTML={{
            __html: language[langKey]
        }} />
    ) : (
            <span className='blurredText'>
                {placeholder}
            </span>
        );
};

TextValue.propTypes = {
    /**
     * The key of the language value to retrieve
     */
    langKey: PropTypes.string.isRequired,
    /**
     * How many blurred words to surface as placeholder elements while waiting for language to flow in
     */
    placeholderWordCount: PropTypes.number
}


function mapStateToProps(state) {
    return {
        language: state.language.values
    };
};

export default connect(mapStateToProps)(TextValue);

This is my TextValue component. I am trying to use it as a prop type in some components as follows:

TextInput.propTypes = {
    /**
     * The name of the form input.
     */
    name: PropTypes.string.isRequired,
    /**
     * The placeholder text to display within the input field. Gets its value from the input name if not supplied.
     */
    placeholder: PropTypes.string,
    /**
     * The input's label.
     */
    label: PropTypes.instanceOf(TextValue).isRequired,
    /**
     * Represents whether or not the input is required in order to submit the form to which it belongs
     */
    required: PropTypes.bool
}

This results in an error from React:

Warning: Failed prop type: Invalid prop 'title' of type 'Object' supplied to 'TextInput', expected instance of 'TextValue'.

Is it possible to check the type of my TextValue export? Since it is a functional component, does it require a different method of enforcing it as a prop type?

jzkarap
  • 31
  • 5

1 Answers1

1

Try PropTypes.element (for a React element, i.e. <MyComponent />) or PropTypes.elementType (for a React element type, i.e. MyComponent) instead of PropTypes.instanceOf:

// ...
    label: PropTypes.elementType.isRequired,
// ...

PropTypes.instanceOf is used for an instance of a JS class not for a React component.

See this answer.

lavor
  • 1,787
  • 1
  • 14
  • 21
  • That is helpful. Is there a way to check the type of an element? "elementType" gets me one step closer but I only want to validate one specific type of element. edit: Looks like "elementType" also throws an Error: `Failed prop type: Invalid prop 'title' of type 'object' supplied to 'TextInput', expected a single ReactElement type.` – jzkarap Nov 20 '19 at 14:59
  • I think it is not possible to validate for specific component type (check documentation here: https://github.com/facebook/prop-types#usage). I don't know what are you passing to the prop, whether it is React element or React element type. Try `PropTypes.element` instead. See my edited answer. – lavor Nov 20 '19 at 15:45