React: Proposal: Validating object against propTypes object outside or render/context flows

Created on 4 May 2016  路  7Comments  路  Source: facebook/react

To avoid using lots of event handling and manual prop chaining inside a parent form, I wrote a component that accumulates form data using a context like so:

import React from 'react';
import RComponent from '...'; // React.Component subclass


let { func, string, object } = React.PropTypes;

class ReactForm extends RComponent {




    constructor(props, context) {
        super(props, context);
        this.displayName = 'ReactForm';
    }




    matchSchema() {
        //...returns true or false
    }



    static get defaultProps() {
        return Object.assign(RComponent.defaultProps, {
            klass: 'form',
            schema: {},
            process: () => {}
        });
    }




    static get propTypes() {
        return Object.assign(RComponent.defaultProps, {
            klass: string.isRequired,
            schema: object.isRequired,
            process: func.isRequired
        });
    }





    getChildContext() {
        let me = this;
        return {
            report(k, v, ok) {  // Input components will take care of themselves and report in here.
                if (ok)
                    me.formdata[k] = v;
                else
                    delete me.formdata[k];                
            }
        };
    }





    onSubmit(e) {
        e.preventDefault();

        if (this.matchSchema())
            this.props.process(this.formdata);
    }






    render() {

        let { klass, children } = this.props;

        return (
            <form className={cx([klass])} onSubmit={this.onSubmit.bind(this)} >
                { children }
            </form>
        );
    }
}


ReactForm.childContextTypes = {
    report: func.isRequired
};


export default ReactForm;

The context just exposes a function where any child (namely an input) reports a final JSON key, value and validation status. Although I could bring in a 3rd party schema validator, I wanted to see if I could leverage the schema property as an object containing React proptypes.

I understand that proptypes don't get checked when rendering in production, but I was hoping that in matchSchema I want to call whatever React uses to take an object and check it against the accumulated form data.

i.e.

<ReactForm schema={ { firstname: React.PropTypes.string.isRequired } } />

From looking at the docs and StackOverflow, it looks like there is no exposed API to just validate against proptypes. The only solution that I can find involves using stateless components and intercepting console messages.

A paranoid solution might look like:

matchSchema() {

    // Prepare stateless components that attemps
    // to render form data 
    let ss = () => <span {...this.formdata} />;
    ss.propTypes = this.props.schema;

    let success = true;

    let { warn, error } = console;
    console.warn = console.error = () => { throw new Error() };

    try {
        ss();
    }
    catch(e) {
        success = false;
    }

    console.warn = warn;
    console.error = error;

    return success;
}

...But this is not going to fly because I don't want to run React in dev mode in production.

Can React expose a way to take advantage of its validation system regardless of its mode, so that I can test an object's shape and property types without hacking around the flow?

Most helpful comment

You can keep using them if you like. They鈥檙e not going away soon.
But longer term the plan is to use something like Flow.
We will emphasize it in docs over PropTypes.

All 7 comments

AFAIK PropTypes are considered legacy and are in maintenance mode. It's unlikely additional development will be happening on them.

@zyrolasting Proptypes do (or will soon) become noop functions in production (to save bytes when downloading React in production mode), so they aren't usable in the production build. Also, as @Aweary mentioned, proptypes are legacy, so we aren't adding new features.

I think your best bet would be to copy-paste the validator code from React into a separate library, which you could then use in production. Or, like you mentioned, use a third party validation library.

I'm going to close this out for the reasons above. Feel free to continue the discussion on this thread.

Thanks for the prompt response, guys. I have nothing else to add given the circumstances. Have a great day!

(sorry, not directly related, but this issue is the first time I've seen proptypes marked as legacy)
@jimfb can you please provide any link / additional info why they're becoming legacy, and what should be used instead of them in the future?
I've just invested some time setting them for our project and find them quite useful, this kind of validations is nice to have in dev.

You can keep using them if you like. They鈥檙e not going away soon.
But longer term the plan is to use something like Flow.
We will emphasize it in docs over PropTypes.

Oh, thanks, Dan. That makes total sense. I've been thinking about overlaps of PropTypes and TypeScript validations just recently.

I tried using Flow in React 15 with create-react-app and flow type errors didn't show up in the create-react-app console, nor did they play nice with standard eslint so I had to abandon it. If we can that last bit of integration working for Flow, it'd be very nice to use.

Was this page helpful?
0 / 5 - 0 ratings