Redux Observable用于表单验证

时间:2019-01-03 19:41:56

标签: javascript reactjs redux rxjs redux-observable

我有一个Formik步骤过程。第一步,用户输入名称。我希望在2个场合中异步检查该名称。

首先,当用户停止输入时,我想对呼叫进行退信,直到用户单击Submit

当用户单击“提交所有步骤”时,我第二次要检查它。

我正在使用React,Redux,Redux-Observable来实现这一目标。

到目前为止,我已经做过什么,我知道我需要做些什么,但是不确定是否以及如何实现。除了以下内容外,我知道我还需要史诗中的另一个pipe方法,然后使用反跳运算符。我还在GitHub(https://github.com/redux-observable/redux-observable/tree/master/examples/redux-form)上阅读了类似的方法,该方法说明了如何使用redux-form来做到这一点,但不确定在这里是否适用。

如果有人知道如何解决此问题,请提出建议。我是RxJS和一般编程人员的新手,这有点让人不知所措。谢谢你。

以下是我到目前为止的代码:

进行了一系列操作:

export const Type = {
  LIST_ITEMS_ATTEMPT: 'LIST_GROUPS_ATTEMPT',
  LIST_ITEMS_SUCCESS: 'LIST_ITEMS_SUCCESS',
  LIST_ITEMS_FAILURE: 'LIST_ITEMS_FAILURE'
};

const listItems = () => ({ type: Type.LIST_ITEMS_ATTEMPT });
const listItemsSuccess = payload => ({ type: Type.LIST_ITEMS_SUCCESS, payload });
const listItemsFailure = error => ({ type: Type.LIST_ITEMS_FAILURE, error });

export const Actions = {
  listItems,
  listItemsSuccess,
  listItemsFailure
};

在史诗中我有这个:

import { of } from 'rxjs';
import { switchMap, map, catchError } from 'rxjs/operators';

import { observableFromHttpPromise, combineAndIsolateEpics } from 'util/epicsUtil';
import { Type as ItemsType, Actions as ItemsActions } from '../actions';

const listItemsEpic = (action$, store, deps) =>
  action$.ofType(ItemsType.LIST_ITEMS_ATTEMPT).pipe(
    switchMap(() =>
      observableFromHttpPromise(deps.listItems()).pipe(
        map(result => ItemssActions.listItemsSuccess(result && result.data)),
        catchError(error => of(ItemsActions.listItemsFailure(error && error.message)))
      )
    )
  );

const itemsSubjectEpics = combineAndIsolateEpics(listItemsEpic);

export default itemsSubjectEpics;

在我的组件中,对于我正在使用的Formik表单:

import React from 'react';
import PropTypes from 'prop-types';
import { Formik } from 'formik';
import * as Yup from 'yup';
import classNames from 'classnames';

import formPropTypes from 'constants/formPropTypes';

const validationSchema = Yup.object().shape({
  name: Yup.string()
    .trim()
    .required('Item name is required.')
});

class ItemsDetailsForm extends React.Component {
  handleSubmit = values => {
    const { id, onSubmit } = this.props;
    onSubmit(id, values);
  };

  render() {
    const { item } = this.props;

    return (
      <Formik
        initialValues={{ ...item }}
        onSubmit={this.handleSubmit}
        validationSchema={validationSchema}
        render={({ values, touched, errors, handleChange, handleBlur, handleSubmit }) => (
          <form onSubmit={handleSubmit}>
            <div className="row">
              <div className="col-md-3">
                <div className="form-group">
                  <label htmlFor="itemName">
                    Item name <span className="text-danger">*</span>
                  </label>
                  <input
                    type="text"
                    onChange={handleChange}
                    onBlur={handleBlur}
                    value={values.name}
                    name="name"
                    className={classNames('form-control', {
                      'is-invalid': errors.name && touched.name
                    })}
                    id="itemName"
                    placeholder="Placeholder"
                  />
                  {!!errors.name && touched.name && (
                    <div className="text-danger">{errors.name}</div>
                  )}
                </div>
                <div className="form-group">
                  <label htmlFor="itemDescription">Description</label>
                  <textarea
                    onChange={handleChange}
                    onBlur={handleBlur}
                    value={values.description}
                    name="description"
                    className={classNames('form-control', {
                      'is-invalid': errors.description && touched.description
                    })}
                    id="itemDescription"
                    rows="3"
                    placeholder=""
                  />
                  {!!errors.description && touched.description && (
                    <div className="text-danger">{errors.description}</div>
                  )}
                </div>
                <button type="submit">Submit</button>
              </div>
            </div>
          </form>
        )}
      />
    );
  }
}

ItemsDetailsForm.propTypes = {
  ...formPropTypes,
  item: PropTypes.object
};

ItemsDetailsForm.defaultProps = {
  item: {
    name: '',
    description: ''
  }
};

export default ItemsDetailsForm;

0 个答案:

没有答案