Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
zyrolasting opened this issue May 4, 2016 · 7 comments

Comments

@zyrolasting
Copy link

zyrolasting commented May 4, 2016

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?

@aweary
Copy link
Contributor

aweary commented May 4, 2016

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

@jimfb
Copy link
Contributor

jimfb commented May 4, 2016

@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.

@jimfb jimfb closed this as completed May 4, 2016
@zyrolasting
Copy link
Author

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

@emirotin
Copy link

(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.

@gaearon
Copy link
Collaborator

gaearon commented Jun 30, 2016

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

@emirotin
Copy link

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

@abcd-ca
Copy link

abcd-ca commented Oct 18, 2017

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants