使用Rekit Saga连接到Firebase Firestore

时间:2018-09-19 13:03:51

标签: reactjs firebase google-cloud-firestore redux-saga

我正在用Rekit Studio创建一个简单的应用程序(联系表单),并使用Redux-Saga将表单连接到Firebase数据库(Firestore)。

我搜索了示例,甚至阅读了所有Rekit文档。 Rekit很棒,但我找不到解决此问题的示例或文档。

我正在使用以下代码来构建页面:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actions from './redux/actions';

import { AvField, AvForm } from 'availity-reactstrap-validation';
import memobind from 'memobind';

export class Form01 extends Component {
  static propTypes = {
    form01: PropTypes.object.isRequired,
    actions: PropTypes.object.isRequired,
  };

  state = {
    name: '',
    email: '',
    formError: false
  };

  validateForm() {
    const hasError = !this.state.name.trim() || !this.state.email.trim();
    this.setState({
      formError: hasError,
    });
    return !hasError;
  }

  handleNameChange(evt) {
    this.setState({
      name: evt.target.value,
    });
  }

  handleEmailChange(evt) {
    this.setState({
      email: evt.target.value,
    });
  }

  handleSubmit(evt) {
    // evt.preventDefault();
    evt.persist();
    if (!this.validateForm()) {
      return;
    }
    this.props.actions
      .saveForm01({
        name: this.state.name,
        email: this.state.email
      })
      .then(() => {
        this.props.history.push('/form-01');
      });
  }

  render() {
    const { saveForm01Error, saveForm01Pending } = this.props.form01;
    const { formError, name, email } = this.state;
    const nameError = formError && !name.trim();
    const emailError = formError && !email.trim();

    return (
      <div className="form-01-form-01">
        <AvForm onSubmit={memobind(this, 'handleSubmit')}>
          <fieldset disabled={saveForm01Pending}>
            <AvField
              name="name"
              type="text"
              placeholder="Nome completo"
              value={this.state.name}
              onChange={memobind(this, 'handleNameChange')}
              required
            />
            {nameError && <div className="error-tip">Name is required.</div>}

            <AvField
              name="email"
              type="email"
              placeholder="E-mail"
              value={this.state.email}
              onChange={memobind(this, 'handleEmailChange')}
              required
            />
            {emailError && <div className="error-tip">E-mail is required.</div>}
          </fieldset>

          <button type="submit" disabled={saveForm01Pending}>
            {saveForm01Pending ? 'Enviando...' : 'Enviar'}
          </button>
          {saveForm01Error && <div className="error-tip">Save form01 failed: {saveForm01Error}</div>}
        </AvForm>
      </div>
    );
  }
}


/* istanbul ignore next */
function mapStateToProps(state) {
  return {
    form01: state.form01,
  };
}

/* istanbul ignore next */
function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators({ ...actions }, dispatch),
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(Form01);

页面呈现没有错误,但是问题是当我连接到Redux / Saga时:

import { all, put, select, takeLatest } from 'redux-saga/effects';
import {
  FORM_01_SAVE_FORM_01_BEGIN,
  FORM_01_SAVE_FORM_01_SUCCESS,
  FORM_01_SAVE_FORM_01_FAILURE,
  FORM_01_SAVE_FORM_01_DISMISS_ERROR,
} from './constants';

import rsf from '../../../rsf';

export function saveForm01(data) {
  // If need to pass args to saga, pass it with the begin action.

  // return {
  //   type: FORM_01_SAVE_FORM_01_BEGIN,
  // };

  return (dispatch) => {
    dispatch({
      type: FORM_01_SAVE_FORM_01_BEGIN,
    });

    const promise = new Promise((resolve, reject) => {
      const Form01 = {};
      const form01 = new Form01();
      form01.save(data).then(() => {
        dispatch({
          type: FORM_01_SAVE_FORM_01_SUCCESS,
          data: {},
        });
        resolve();
      }, (err) => {
        dispatch({
          type: FORM_01_SAVE_FORM_01_FAILURE,
          data: {
            error: err,
          },
        });
        reject();
      });
    });

    return promise;
  };
}

export function dismissSaveForm01Error() {
  return {
    type: FORM_01_SAVE_FORM_01_DISMISS_ERROR,
  };
}

// worker Saga: will be fired on FORM_01_SAVE_FORM_01_BEGIN actions
export function* doSaveForm01() {
  // If necessary, use argument to receive the begin action with parameters.
  let res;
  try {
    // Do Ajax call or other async request here. delay(20) is just a placeholder.

    const newForm01a = yield select(state => state.listForm01.name);
    const newForm01b = yield select(state => state.listForm01.email);

    res = yield all(
      rsf.firestore.addDocument,
      'Form01',
      {
        nome: newForm01a,
        email: newForm01b
      },
    );
  } catch (err) {
    yield put({
      type: FORM_01_SAVE_FORM_01_FAILURE,
      data: { error: err },
    });
    return;
  }
  // Dispatch success action out of try/catch so that render errors are not catched.
  yield put({
    type: FORM_01_SAVE_FORM_01_SUCCESS,
    data: res,
  });
}

/*
  Alternatively you may use takeEvery.

  takeLatest does not allow concurrent requests. If an action gets
  dispatched while another is already pending, that pending one is cancelled
  and only the latest one will be run.
*/
export function* watchSaveForm01() {
  yield takeLatest(FORM_01_SAVE_FORM_01_BEGIN, doSaveForm01);
}

// Redux reducer
export function reducer(state, action) {
  switch (action.type) {
    case FORM_01_SAVE_FORM_01_BEGIN:
      return {
        ...state,
        saveForm01Pending: true,
        saveForm01Error: null,
      };

    case FORM_01_SAVE_FORM_01_SUCCESS:
      return {
        ...state,
        saveForm01Pending: false,
        saveForm01Error: null,
      };

    case FORM_01_SAVE_FORM_01_FAILURE:
      return {
        ...state,
        saveForm01Pending: false,
        saveForm01Error: action.data.error,
      };

    case FORM_01_SAVE_FORM_01_DISMISS_ERROR:
      return {
        ...state,
        saveForm01Error: null,
      };

    default:
      return state;
  }
}

有人可以给我点灯吗?

0 个答案:

没有答案