Formsy React

簡單記錄目前使用 Formsy React 的狀況並與其他 library 做小小比較。

如何用?

表單相關的會使用 <Formsy /> 所提供的 API,而 input 元件則會包在 withFormsy 這個 HOC 裡面來取得其可用的屬性和方法,可參考官方網站的 Quick StartAPIExamples

優點

缺點

報錯訊息單數與複數使用不同屬性

單數(validationError)、複數(validationErrors),容易誤用或經常修改。

validationError:只有一個驗證規則,只需要一個報錯訊息。

<MyInput name='email' validations='isEmail' validationError='This is not an email' />

validationErrors:多個驗證規則,需要多個報錯訊息。

<MyInput
  name='email'
  validations=
  validationErrors=
/>

驗證規則與報錯的設定

Formsy 的驗證規則與報錯訊息是放在兩個不同的 props-validations 和 validationErrors,比較麻煩;相較之下 Formik 將驗證規則與錯誤訊息放在一起是比較好整理的。

Formsy

<MyInput
  name='email'
  validations=
  validationErrors=
/>

Formik & Yup

validationSchema: yup.object().shape({
  name: yup
    .string()
    .required("必填")
    .min(4, "字數必須超過 3 個字"),
  email: yup
    .string()
    .required("必填")
    .isEmail("不合法的 Email,@ 前後必須為英數")
}),

required vs 其他驗證規則

required 是一個屬性,與其他驗證規則不同。

<MyInput
  name='email'
  required
  validations=
  validationErrors=
/>

若希望 required 為一般的驗證規則而能統計整個錯誤訊息個數,可經由 addValidationRule 自行實作並加入 required 這個規則。

自行定義 required 這個規則。

addValidationRule('required', (values, value) => {
  return !String(value).trim() === '';
});

在驗證規則中使用自定義的 required 規則而非 required 屬性。

<MyInput
  name='email'
  label='Email'
  validations=
  validationErrors=
/>

但若使用 required 屬性就無法在統計錯誤訊息時將必填一起統計進去。如下範例所示,Name 欄位沒有填任何東西,Email 欄位填寫不正確格式的字串「123」,我們期待 Name 欄位會有「Required.」、Email 欄位會有「Illegal email address.」錯誤訊息;對照實際取得的 errors,Name 欄位沒有錯誤訊息。

Formsy

點此看完整範例。

API 不足以處理表單資訊

外部無法取得目前表單各欄位的錯誤訊息,必須要自己提取各個 input 元件的資訊後再組成整個表單的狀態(範例)。

沒有內建機制做 dirty check

沒有內建機制做 dirty check,要自己比對 pristine 與 initial value 來判斷是否 dirty。

const {
  isPristine, // API 提供
  getValue, // API 提供
  initialValue, // 自己存
} = this.props;

if (!isPristine() && getValue() !== initialValue) {
  // this field is dirty...
}

點此看完整範例。

客製化元件必須自定義取值和設值的 method

客製化元件必須自定義取值和設值的 method,比較麻煩,如下所示的 changeValue,不像 Formik 或 Redux Form 會自動對應。

class MyInput extends Component {
  constructor(props) {
    super(props);
    this.changeValue = this.changeValue.bind(this);
  }

  // setValue() will set the value of the component, which in turn will validate it and the rest of the form
  // Important: Don't skip this step. This pattern is required for Formsy to work.
  changeValue(event) {
    this.props.setValue(event.currentTarget.value);
  }

  render() {
    return (
      <input type='text' value={this.props.getValue() || initial} onChange={this.changeValue} />
    );
  }
}

export default withFormsy(MyInput);

點此看完整範例。

無法做條件式判斷或嵌套驗證規則

無法做條件式判斷或嵌套驗證規則,靈活度較低,相較 Formik & Yup 卻是可以做到的。

設定初始值後在送出時會為 undefined

這是 bug 嘛?若在 input 設定初始值,則在送出時會為 undefined。

Formsy

點此看完整範例。

小結

用到目前為止覺得雷很多(?)不太能滿足實作上的需求…歡迎大大們提供意見,感謝。

資料來源


comments powered by Disqus