使用redux saga和redux格式在react app中显示表单错误

时间:2017-11-10 09:00:58

标签: javascript reactjs redux redux-form redux-saga

我试图弄清楚如何使用redux saga在我的登录redux表单中显示错误。我能够发出请求,但如果响应是403 - 禁止,我需要以某种方式向用户显示消息。

系统:

  • react 16.0.0
  • redux 3.7.2
  • redux-form 7.1.2
  • redux-saga 0.16.0

登录-form.js

import React, {Component} from 'react';
import {Field, reduxForm} from 'redux-form';
import {connect} from 'react-redux';

import {submit} from '../../actions';

class Login extends Component {
  constructor(props) {
    super(props);

    this.onSubmit = this.onSubmit.bind(this);
  }

  onSubmit(values) {
    this.props.submit(values);
  }

  renderField(field, label) {
    // ommited
  }

  render() {
    const {handleSubmit, error} = this.props;

    return (
      <Form onSubmit={handleSubmit(this.onSubmit)}>

        {error ? error : ''}

        <Field
          name="email"
          label="Email*"
          type="email"
          placeholder="Email"
          component={this.renderField}
        />
        <Field
          name="password"
          label="Heslo*"
          type="password"
          placeholder="Heslo"
          component={this.renderField}
        />
        <Button color="primary">Login</Button>
      </Form>
    );
  }
}

export default reduxForm({
  form: 'loginForm'
})(
  connect(null, {submit})(Login)
);

actions.js:

export const submit = function(data) {
  console.log("Action:", data);
  return {
    type: 'REQUEST_SUBMIT',
    data: data
  };
};

sagas.js:

import {takeEvery, fork, call, put} from 'redux-saga/effects';
import axios from 'axios';
import {SubmissionError} from 'redux-form';

async function submitToServer(data) {
  try {
    let response = await axios.post('http://localhost:3000/login', data);
    yield put({type: 'REQUEST_SUCCESSFUL', payload: result.data})
  } catch(error) {
    throw new SubmissionError({_error: "Some error message"});
  }
}

function* callSubmit(action) {
  yield call(submitToServer, action.data);
}

function* submitSaga() {
  yield takeEvery('REQUEST_SUBMIT', callSubmit);
}

export default function* root() {
  yield [
    fork(submitSaga)
  ];
}

一切都按预期工作,但我无法弄清楚如何实际使登录表单显示我的传奇中抛出的错误消息。我应该在我的传奇中投掷SubmissionError还是有更好的方法呢?

4 个答案:

答案 0 :(得分:1)

在提交请求调用之前在中间件中 yield put(startSubmit(formId))

在错误处理块中调用 yield put(stopSubmit(formId, { _error: 'Connection error' }))

如果没有错误发生,您可以直接致电 yield put(stopSubmit(formId)) 表示表单已成功提交。

startSubmitstopSubmit函数可以从'redux-form'导入

redux表单组件prop error将是字符串'Connection error'。

答案 1 :(得分:0)

这通常是redux全球状态发挥作用的地方。

您的actions.js文件显示了一种操作类型:REQUEST_SUBMIT。我假设那里还有REQUEST_SUCCESSFUL,因为当api调用超过时你在你的传奇中发送它。

对于像http请求这样的异步内容,您可能会对整个请求/响应/错误流进行3次操作。

当您在传奇中捕获该异常时,您将发送此第3个REQUEST_FAILED操作,并将错误消息作为操作负载。

yield put({ type: 'REQUEST_FAILED, payload: error });

然后在reducers.js中,您的reducer会侦听此操作类型,然后使用您的错误消息更新状态。

最后,在您的组件中,您可以通过定义mapStateToProps函数来访问您所在州的此错误消息,并将其传递给connect来电。 这部分几乎是react-redux lib的入门文档中的内容。

答案 2 :(得分:0)

Redux-form希望提交处理程序返回一个promise,并显示被拒绝的错误。

最简单的方法是使用一些胶水代码,例如:https://github.com/mhssmnn/redux-form-sagahttps://github.com/afitiskin/redux-saga-routines

这是非常简单的胶水代码:

  • 回复承诺
  • 使用解析/拒绝处理程序发送操作
  • 使用传奇从该
  • 触发特定于表单的操作
  • 从您的传奇,调度表格特定的成功/失败行动
  • 胶水调用解决/拒绝承诺,具体取决于所谓的

或者,您可以使用redux-form动作创建器手动设置字段错误:https://redux-form.com/7.1.2/docs/api/actioncreators.md/

答案 3 :(得分:0)

我刚刚处理了同样的问题。当您使用键入SubmissionError的消息抛出_error时,该消息将填充在表单的error道具中。它不会填充在表单字段的meta.error prop中,这是我的验证错误填充的位置。

我正在使用&#34; renderField&#34;的变体。以下示例中使用的组件:https://redux-form.com/6.0.0-rc.1/examples/syncvalidation/。我更新了这个组件:

  1. 在表单中,将错误道具传递给<Field />组件。 我将道具命名为#a; ajaxSubmitError&#34;将其与验证错误区分开来。

  2. 在&#34; renderField&#34;组件,在渲染错误时为ajaxSubmitError(或任何你决定命名的名称)添加条件检查。

  3. 希望有所帮助。

    <强>更新

    我刚刚想到我的用例非常具体,所以我会根据我的回答给出一些背景信息。我正在做一个&#34;向导&#34;表单,这意味着我一次只显示一个字段。除此之外,我还要在每个&#34;步骤&#34;上将数据发布到后端API。表单的形式,而不是在窗体的末尾发出一个POST请求。这是我希望提交错误显示在特定字段的上下文中(一次只显示一个字段)。

    假设您没有使用向导表单,您可能只想在表单中添加一个组件,如果表单上有错误道具,则会有条件地呈现。