question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Proposal: Using pure es6 base classes over Formsy.Mixins

See original GitHub issue

I got Formsy working with pure es6 classes with some minor scaffolding. I wish to contribute it back so that Formsy can become pure es6 Object oriented without any Mixin.

I have been experimenting creating Formsy.Mixin a class and have been able to make it work with the following

import React from 'react';

/** 
 * The base component that autobinds all the methods to this.
 */
class BaseComponent extends React.Component {
  constructor(props) {
    super(props);
    Object.getOwnPropertyNames(Object.getPrototypeOf(this)).forEach((method) => {
      if (typeof this[method] !== 'function') {
        return;
      }
      this[method] = this[method].bind(this);
    });
  }
}

export default BaseComponent;
import Formsy from 'formsy-react';

import BaseComponent from 'components/BaseComponent';

/**
 * The base component that binds all Formsy Mixin methods so that they can be extended by es6 Formsy components.
 */
class FormComponent extends BaseComponent {
  static defaultProps = {
    validationError: '',
    validationErrors: {}
  }

  constructor(props) {
    super(props);

    this.state = Object.assign(this.state || {}, Formsy.Mixin.getInitialState.bind(this)());
    Object.getOwnPropertyNames(Formsy.Mixin).forEach((method) => {
      if (typeof Formsy.Mixin[method] !== 'function') {
        return;
      }
      if (method === 'getDefaultProps' || method === 'getInitialState') {
        return;
      }
      this[method] = Formsy.Mixin[method].bind(this);
    });
  }
}

export default FormComponent;

Now a new form component is simply.

class MyFormComponent extends FormComponent {
}

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:4
  • Comments:29 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
mindcruzercommented, Oct 9, 2015

In case anyone is interested in type declarations for TypeScript:

// Formsy.d.ts
// Type definitions for Formsy-React
// Project: https://github.com/christianalfoni/formsy-react

declare module Formsy {

    interface ValidationErrors {
        [key: string]: string;
    }

    // This is declared for a reference to Formsy.Mixin in FormsyFormComponent.ts
    var Mixin: any;

    interface FormProps {
        className?: string;
        mapping?: Function;
        onSuccess?: Function;
        onError?: Function;
        onSubmit?: Function;
        onValidSubmit?: Function; 
        onInvalidSubmit?: Function;
        onSubmitted?: Function;
        onValid?: Function;
        onInvalid?: Function;
        onChange?: Function;
        validationErrors?: ValidationErrors;
        preventExternalValidation?: boolean;
    }

    class Form extends React.Component<FormProps, any> { }
}
// FormsyFormComponent.ts
// Type wrapper for Formsy-React
// Project: https://github.com/christianalfoni/formsy-react

/*
 * Here the Formsy.Mixin is wrapped as an abstract class, so that it can 
 * be used effectively with TypeScript.
 */
namespace Formsy {

    export interface FormComponentProps {
        name: string;
        value?: any;
        validations?: string;
        validationError?: string;
        validationErrors?: ValidationErrors;
        required?: boolean;
        _validate?: Function;
    }

    export interface FormComponentState {
        _value: any;
        _isRequired: boolean;
        _isValid: boolean;
        _isPristine: boolean;
        _pristineValue: any,
        _validationError: string;
        _externalError: string;
        _formSubmitted: boolean;
    }

    export abstract class FormComponent<V, P extends FormComponentProps, S extends FormComponentState> extends React.Component<P, S> {

        static defaultProps: FormComponentProps = {
            name: null,  // this can be set to whatever, since it will be overwritten when child components are created
            validationError: '',
            validationErrors: {}
        };

        constructor(props: P) {
            super(props);

            // Default values for state
            this.state = <S>Mixin.getInitialState.call(this);
        }

        // Lifecycle methods
        componentWillMount() {
            Mixin.componentWillMount.call(this);
        }

        componentWillReceiveProps(nextProps: P) {
            Mixin.componentWillReceiveProps.call(this, nextProps);
        }

        componentDidUpdate(prevProps: P) {
            Mixin.componentDidUpdate.call(this, prevProps);
        }

        componentWillUnmount() {
            Mixin.componentWillUnmount.call(this);
        }

        // Formsy methods
        setValue(value: V) {
            Mixin.setValue.call(this, value);
        }

        resetvalue() {
            Mixin.resetValue.call(this);
        }

        getValue() {
            return <V>Mixin.getValue.call(this);
        }

        hasValue() {
            return <boolean>Mixin.hasValue.call(this);
        }

        getErrorMessage() {
            return <string>Mixin.getErrorMessage.call(this);
        }

        isFormDisabled() {
            return <boolean>Mixin.isFormDisabled.call(this);
        }

        isValid() {
            return <boolean>Mixin.isValid.call(this);
        }

        isPristine() {
            return <boolean>Mixin.isPristine.call(this);
        }

        isFormSubmitted() {
            return <boolean>Mixin.isFormSubmitted.call(this);
        }

        isRequired() {
            return <boolean>Mixin.isRequired.call(this);
        }

        showRequired() {
            return <boolean>Mixin.showRequired.call(this);
        }

        showError() {
            return <boolean>Mixin.showError.call(this);
        }

        isValidValue(value: any) {
            return <boolean>Mixin.isValidValue.call(this);
        }

        private setValidations(validations: string, required: boolean) {
            Mixin.setValidations.call(this, validations, required);
        }
    }
}

Example use:

namespace MyProject.Components {

    interface CheckboxInputProps extends Formsy.FormComponentProps {
        label: string;
        disabled?: boolean;
        onChange?: (checked: boolean) => any
    }

    /**
     * Checkbox control for inclusion in Formsy forms.
     */
    export class CheckboxInput extends Formsy.FormComponent<boolean, CheckboxInputProps, any> {

        constructor(props: CheckboxInputProps) {
            super(props);
        }

        render() {
            return (
                <label>
                    <input type="checkbox" checked={ this.getValue() } disabled={ this.props.disabled }
                           onChange={ this._onChange } /> { this.props.label }
                </label>
            );
        }

        private _onChange = (e: React.FormEvent) => {
            var checked = (e.nativeEvent.srcElement as HTMLInputElement).checked;

            this.setValue(checked);

            if (this.props.onChange) {
                this.props.onChange(checked);
            }
        } 
    }
}
2reactions
robin-anilcommented, Apr 5, 2016

FWIW, My team, is actively migrating away from Formsy to redux-form. We have tried to get the most out of Formsy. However redux has taken over our world, and redux-form solves some of the weird data cycles we see with Formsy and we find it easier to build form components with it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Proposal: Using pure es6 base classes over Formsy.Mixins
I got Formsy working with pure es6 classes with some minor scaffolding. I wish to contribute it back so that Formsy can become...
Read more >
Mixins Are Dead. Long Live Composition | by Dan Abramov
The introductory post made it clear that mixins are on their way out: Unfortunately, we will not launch any mixin support for ES6...
Read more >
Mixins Considered Harmful – React Blog
We understand that more typing can be annoying. For the most common case, we plan to introduce a new base class called React.PureComponent...
Read more >
What is the best way to use mixins in js? - Stack Overflow
The "mixins" are classes, created instantly by class-factories. They always extend another class. Thus it is pure inheritance. And even though ...
Read more >
Please stop using classes in JavaScript - everyday.codes
Pre-ES6 classes. Even though the class keyword was added to JavaScript since ES6 (ECMAScript 2015), people were using classes earlier. The way ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found