jurassix / react-validation-mixin

Simple validation mixin (HoC) for React.
MIT License
282 stars 38 forks source link

ES6: missing props on validation #45

Closed Volodymyr128 closed 9 years ago

Volodymyr128 commented 9 years ago

I'm using react + es6, so to pass props of Step1 component I need to pass them as super(props) at constructor. Step1 is route-handler (I use react-router) so it's the only way to pass props in it. The problem is that I miss all my custom properties on this.props.validate(). Look at the example below please (pay attention to _onChange & 'render' method comments).

const React = require('react/addons'),
         Component = React.Component,
         validation   = require('react-validation-mixin'),
         strategy = require('joi-validation-strategy'),
         Joi = require('joi');

const customizations = {
    stepNo: 1,
    progress: '1/3',
    title: 'some title'
};

class Step1 extends Component {

    constructor(props) {
        super(_.assign(props, customizations)); // <======= pass props to route-handler
        this.validatorTypes = this._getValidatorTypes();
        this.getValidatorData = this.getValidatorData.bind(this);
        this._onChange = this._onChange.bind(this);
    }

    getValidatorData() {
        return this.state;
    }

    render() {
        // this.props.title === 'some title' on initial render, 
        //BUT PROBLEM - it's undefined after this.props.validate (_onChange call)
        const self = this;
        return React.addons.createFragment({
            email: <InputBlock
                onChange={this._onChange.bind(self)}/>,
            ......

        });
    }

    _onChange(newState) { // <================== look here pls
        this.state = newState;
        //PROBLEM: it invokes render, and `customizations` props are missed
        this.props.validate();
    }

    _getValidatorTypes() {
        return {
            email: Joi.string().email().min(5).max(50).required(),
            ..........
        };
    }
}

Step1.propTypes = {
    errors: PropTypes.object,
    validate: PropTypes.func,
    isValid: PropTypes.func,
    handleValidation: PropTypes.func,
    getValidationMessages: PropTypes.func,
    clearValidations: PropTypes.func
};

module.exports = validation(strategy)(Step1);
jurassix commented 9 years ago

The issue here appears to be the way you are mixing in default props and expecting them to be maintained. When you call super(_.assign(props, customizations)); this is a one-time assignment. Every time your component is rendered these props are not passed down from the parent and so they are unavailable to your component.

You have two options to fix:

Use defaultProps:

Step1.defaultProps = {
    stepNo: 1,
    progress: '1/3',
    title: 'some title'
};

module.exports = validation(strategy)(Step1);

Or actually pass these variables from the parent:

<Step1 stepNo={1} progress={'1/3'} title={'some title'} />
Volodymyr128 commented 9 years ago

Thanks!!!!!