react / redux-form:如何 return 从 onSubmit 承诺?
react / redux-form: how to return promise from onSubmit?
我正在努力思考 redux, react-redux and redux-form。
我已经设置了一个商店并从 redux-form 添加了 reducer。我的表单组件如下所示:
登录表单
import React, {Component, PropTypes} from 'react'
import { reduxForm } from 'redux-form'
import { login } from '../../actions/authActions'
const fields = ['username', 'password'];
class LoginForm extends Component {
onSubmit (formData, dispatch) {
dispatch(login(formData))
}
render() {
const {
fields: { username, password },
handleSubmit,
submitting
} = this.props;
return (
<form onSubmit={handleSubmit(this.onSubmit)}>
<input type="username" placeholder="Username / Email address" {...username} />
<input type="password" placeholder="Password" {...password} />
<input type="submit" disabled={submitting} value="Login" />
</form>
)
}
}
LoginForm.propTypes = {
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
}
export default reduxForm({
form: 'login',
fields
})(LoginForm)
这按预期工作,在 redux DevTools 我可以看到商店如何在表单输入和提交表单时更新 login
操作创建者调度登录操作。
我添加了 redux-thunk middleware to the store and setup the action creator(s) for logging in as described in the redux docs for Async Actions:
authActions.js
import ApiClient from '../apiClient'
const apiClient = new ApiClient()
export const LOGIN_REQUEST = 'LOGIN_REQUEST'
function requestLogin(credentials) {
return {
type: LOGIN_REQUEST,
credentials
}
}
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS'
function loginSuccess(authToken) {
return {
type: LOGIN_SUCCESS,
authToken
}
}
export const LOGIN_FAILURE = 'LOGIN_FAILURE'
function loginFailure(error) {
return {
type: LOGIN_FAILURE,
error
}
}
// thunk action creator returns a function
export function login(credentials) {
return dispatch => {
// update app state: requesting login
dispatch(requestLogin(credentials))
// try to log in
apiClient.login(credentials)
.then(authToken => dispatch(loginSuccess(authToken)))
.catch(error => dispatch(loginFailure(error)))
}
}
同样,在 redux DevTools 中,我可以看到这按预期工作。当在 LoginForm 的 onSubmit
中调用 dispatch(login(formData))
时,首先调度 LOGIN_REQUEST
操作,然后调度 LOGIN_SUCCESS
或 LOGIN_FAILURE
。 LOGIN_REQUEST
将向商店添加 属性 state.auth.pending = true
,LOGIN_SUCCESS
和 LOGIN_FAILURE
将删除此 属性。 (我知道这可能是我可以使用 reselect 的东西,但现在我想保持简单。
现在,在我读到的 redux-form 文档中,我可以 return 来自 onSubmit
的承诺来更新表单状态(submitting
、error
)。但我不确定这样做的正确方法是什么。 dispatch(login(formData))
returns undefined
.
我可以将商店中的 state.auth.pending
标志与变量 state.auth.status
交换,值 requested、success 和 failure(同样,我可能会为此使用重新选择或类似的东西)。
然后我可以订阅 onSubmit
中的商店并像这样处理对 state.auth.status
的更改:
// ...
class LoginForm extends Component {
constructor (props) {
super(props)
this.onSubmit = this.onSubmit.bind(this)
}
onSubmit (formData, dispatch) {
const { store } = this.context
return new Promise((resolve, reject) => {
const unsubscribe = store.subscribe(() => {
const state = store.getState()
const status = state.auth.status
if (status === 'success' || status === 'failure') {
unsubscribe()
status === 'success' ? resolve() : reject(state.auth.error)
}
})
dispatch(login(formData))
}).bind(this)
}
// ...
}
// ...
LoginForm.contextTypes = {
store: PropTypes.object.isRequired
}
// ...
但是,这个解决方案感觉不太好,我不确定它是否会在应用程序增长时始终按预期工作,并且可能会从其他来源调度更多操作。
我看到的另一个解决方案是将 api 调用(return 是一个承诺)移动到 onSubmit
,但我想将它与 React 组件分开。
对此有何建议?
dispatch(login(formData))
returns undefined
Any return value from the inner function will be available as the return value of dispatch
itself.
所以,你想要像
这样的东西
// thunk action creator returns a function
export function login(credentials) {
return dispatch => {
// update app state: requesting login
dispatch(requestLogin(credentials))
// try to log in
apiClient.login(credentials)
.then(authToken => dispatch(loginSuccess(authToken)))
.catch(error => dispatch(loginFailure(error)))
return promiseOfSomeSort;
}
}
我正在努力思考 redux, react-redux and redux-form。
我已经设置了一个商店并从 redux-form 添加了 reducer。我的表单组件如下所示:
登录表单
import React, {Component, PropTypes} from 'react'
import { reduxForm } from 'redux-form'
import { login } from '../../actions/authActions'
const fields = ['username', 'password'];
class LoginForm extends Component {
onSubmit (formData, dispatch) {
dispatch(login(formData))
}
render() {
const {
fields: { username, password },
handleSubmit,
submitting
} = this.props;
return (
<form onSubmit={handleSubmit(this.onSubmit)}>
<input type="username" placeholder="Username / Email address" {...username} />
<input type="password" placeholder="Password" {...password} />
<input type="submit" disabled={submitting} value="Login" />
</form>
)
}
}
LoginForm.propTypes = {
fields: PropTypes.object.isRequired,
handleSubmit: PropTypes.func.isRequired,
submitting: PropTypes.bool.isRequired
}
export default reduxForm({
form: 'login',
fields
})(LoginForm)
这按预期工作,在 redux DevTools 我可以看到商店如何在表单输入和提交表单时更新 login
操作创建者调度登录操作。
我添加了 redux-thunk middleware to the store and setup the action creator(s) for logging in as described in the redux docs for Async Actions:
authActions.js
import ApiClient from '../apiClient'
const apiClient = new ApiClient()
export const LOGIN_REQUEST = 'LOGIN_REQUEST'
function requestLogin(credentials) {
return {
type: LOGIN_REQUEST,
credentials
}
}
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS'
function loginSuccess(authToken) {
return {
type: LOGIN_SUCCESS,
authToken
}
}
export const LOGIN_FAILURE = 'LOGIN_FAILURE'
function loginFailure(error) {
return {
type: LOGIN_FAILURE,
error
}
}
// thunk action creator returns a function
export function login(credentials) {
return dispatch => {
// update app state: requesting login
dispatch(requestLogin(credentials))
// try to log in
apiClient.login(credentials)
.then(authToken => dispatch(loginSuccess(authToken)))
.catch(error => dispatch(loginFailure(error)))
}
}
同样,在 redux DevTools 中,我可以看到这按预期工作。当在 LoginForm 的 onSubmit
中调用 dispatch(login(formData))
时,首先调度 LOGIN_REQUEST
操作,然后调度 LOGIN_SUCCESS
或 LOGIN_FAILURE
。 LOGIN_REQUEST
将向商店添加 属性 state.auth.pending = true
,LOGIN_SUCCESS
和 LOGIN_FAILURE
将删除此 属性。 (我知道这可能是我可以使用 reselect 的东西,但现在我想保持简单。
现在,在我读到的 redux-form 文档中,我可以 return 来自 onSubmit
的承诺来更新表单状态(submitting
、error
)。但我不确定这样做的正确方法是什么。 dispatch(login(formData))
returns undefined
.
我可以将商店中的 state.auth.pending
标志与变量 state.auth.status
交换,值 requested、success 和 failure(同样,我可能会为此使用重新选择或类似的东西)。
然后我可以订阅 onSubmit
中的商店并像这样处理对 state.auth.status
的更改:
// ...
class LoginForm extends Component {
constructor (props) {
super(props)
this.onSubmit = this.onSubmit.bind(this)
}
onSubmit (formData, dispatch) {
const { store } = this.context
return new Promise((resolve, reject) => {
const unsubscribe = store.subscribe(() => {
const state = store.getState()
const status = state.auth.status
if (status === 'success' || status === 'failure') {
unsubscribe()
status === 'success' ? resolve() : reject(state.auth.error)
}
})
dispatch(login(formData))
}).bind(this)
}
// ...
}
// ...
LoginForm.contextTypes = {
store: PropTypes.object.isRequired
}
// ...
但是,这个解决方案感觉不太好,我不确定它是否会在应用程序增长时始终按预期工作,并且可能会从其他来源调度更多操作。
我看到的另一个解决方案是将 api 调用(return 是一个承诺)移动到 onSubmit
,但我想将它与 React 组件分开。
对此有何建议?
dispatch(login(formData))
returnsundefined
Any return value from the inner function will be available as the return value of
dispatch
itself.
所以,你想要像
这样的东西// thunk action creator returns a function
export function login(credentials) {
return dispatch => {
// update app state: requesting login
dispatch(requestLogin(credentials))
// try to log in
apiClient.login(credentials)
.then(authToken => dispatch(loginSuccess(authToken)))
.catch(error => dispatch(loginFailure(error)))
return promiseOfSomeSort;
}
}