使用redux-form和Fetch API进行服务器验证 [英] Make server validation using redux-form and Fetch API
问题描述
如何使用 redux-form 和Fetch API进行服务器端验证?
演示中提供了 提交验证演示表示建议进行服务器端验证的方法的文档是从onSubmit函数返回promise。但是我应该把那个承诺放在哪里?
据我了解,onSubmit函数应该是我的操作。
How to make server-side validation using redux-form and Fetch API? There are "Submit Validation" demo provided in the docs which says that recommended way to do server side validation is to return a promise from the onSubmit function. But where should I place that promise? As I understood onSubmit function should be my action.
<form onSubmit={this.props.addWidget}>...
以下是this.props.addWidget实际上是我的操作的地方。
Where this.props.addWidget is actually my action, provided below.
import fetch from 'isomorphic-fetch';
...
function fetchAddWidget(widget, workspace) {
return dispatch => {
dispatch(requestAddWidget(widget, workspace));
return fetch.post(`/service/workspace/${workspace}/widget`, widget)
.then(parseJSON)
.then(json => {
dispatch(successAddWidget(json, workspace));
DataManager.handleSubscribes(json);
})
.catch(error => popupErrorMessages(error));
}
}
export function addWidget(data, workspace) {
return (dispatch, getState) => {
return dispatch(fetchAddWidget(data, workspace));
}
}
如您所见,我使用提取API。我原以为获取会返回promise,而redux-form会捕获它,但这是行不通的。如何通过示例与诺言一起使用?
As you see I use fetch API. I expected that fetch will return promise and redux-form will catch it but that doesn't work. How to make it work with promise from example?
从演示中我也无法理解this.props.handleSubmit函数中应该提供什么。
Also from the demo I can not understand what should be provided in this.props.handleSubmit function. Demo does not explain this part, as for me.
推荐答案
这是我对基于 http://erikras.github.io/redux-form/#/examples/submit-validation
- ...但是我应该在哪里放置该承诺?
- ...在this.props.handleSubmit中应该提供什么?
详细信息是在下面的评论中;抱歉,代码块需要滚动才能读取:/
The detail is in the comments below; sorry that the code blocks require a bit of scrolling to read :/
import React, { Component, PropTypes } from 'react';
import { reduxForm } from 'redux-form';
import { myHandleSubmit, show as showResults } from '../redux/modules/submission';
class SubmitValidationForm extends Component {
// the following three props are all provided by the reduxForm() wrapper / decorator
static propTypes = {
// the field names we passed in the wrapper;
// each field is now an object with properties:
// value, error, touched, dirty, etc
// and methods onFocus, onBlur, etc
fields: PropTypes.object.isRequired,
// handleSubmit is _how_ to handle submission:
// eg, preventDefault, validate, etc
// not _what_ constitutes or follows success or fail.. that's up to us
// I must pass a submit function to this form, but I can either:
// a) import or define a function in this component (see above), then:
// `<form onSubmit={ this.props.handleSubmit(myHandleSubmit) }>`, or
// b) pass that function to this component as
// `<SubmitValidationForm onSubmit={ myHandleSubmit } etc />`, then
// `<form onSubmit={this.props.handleSubmit}>`
handleSubmit: PropTypes.func.isRequired,
// redux-form listens for `reject({_error: 'my error'})`, we receive `this.props.error`
error: PropTypes.string
};
render() {
const { fields: { username, password }, error, handleSubmit } = this.props;
return (
<form onSubmit={ handleSubmit(myHandleSubmit) }>
<input type="text" {...username} />
{
// this can be read as "if touched and error, then render div"
username.touched && username.error && <div className="form-error">{ username.error }</div>
}
<input type="password" {...password} />
{ password.touched && password.error && <div className="form-error">{ password.error }</div> }
{
// this is the generic error, passed through as { _error: 'something wrong' }
error && <div className="text-center text-danger">{ error }</div>
}
// not sure why in the example @erikras uses
// `onClick={ handleSubmit }` here.. I suspect a typo.
// because I'm using `type="submit"` this button will trigger onSubmit
<button type="submit">Log In</button>
</form>
);
}
}
// this is the Higher Order Component I've been referring to
// as the wrapper, and it may also be written as a @decorator
export default reduxForm({
form: 'submitValidation',
fields: ['username', 'password'] // we send only field names here
})(SubmitValidationForm);
../ redux /modules/submission.js
../redux/modules/submission.js
// (assume appropriate imports)
function postToApi(values) {
return fetch( API_ENDPOINT, {
credentials: 'include',
mode: 'cors',
method: 'post',
body: JSON.stringify({values}),
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': CSRF_TOKEN
}
}).then( response => Promise.all([ response, response.json()] ));
}
export const myHandleSubmit = (values, dispatch) => {
dispatch(startLoading());
return new Promise((resolve, reject) => {
// postToApi is a wrapper around fetch
postToApi(values)
.then(([ response, json ]) => {
dispatch(stopLoading());
// your statuses may be different, I only care about 202 and 400
if (response.status === 202) {
dispatch(showResults(values));
resolve();
}
else if (response.status === 400) {
// here I expect that the server will return the shape:
// {
// username: 'User does not exist',
// password: 'Wrong password',
// _error: 'Login failed!'
// }
reject(json.errors);
}
else {
// we're not sure what happened, but handle it:
// our Error will get passed straight to `.catch()`
throw(new Error('Something went horribly wrong!'));
}
})
.catch( error => {
// Otherwise unhandled server error
dispatch(stopLoading());
reject({ _error: error });
});
});
};
如果我错过了,请发表评论东西/曲解,等等,我会修正:)
Please chime in with comments if I've missed something / misinterpreted, etc, and I'll amend :)
这篇关于使用redux-form和Fetch API进行服务器验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!