x-r*_*ray 15 javascript forms reactjs redux redux-form
我试图围绕redux,react-redux和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)
Run Code Online (Sandbox Code Playgroud)
这可以按预期工作,在redux DevTools中,我可以看到如何在表单输入上更新商店,以及在提交表单时login动作创建者调度登录操作.
我将redux-thunk中间件添加到商店并设置用于登录的操作创建者,如异步操作的redux文档中所述:
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)))
}
}
Run Code Online (Sandbox Code Playgroud)
同样,在redux DevTools中,我可以看到它按预期工作.当dispatch(login(formData))被称为onSubmit在LoginForm的,第一个LOGIN_REQUEST动作是出动,其次是LOGIN_SUCCESS或LOGIN_FAILURE.LOGIN_REQUEST将一个属性添加state.auth.pending = true到店,LOGIN_SUCCESS并LOGIN_FAILURE会删除该属性.(我知道这可能是我使用重新选择的东西,但是现在我想保持简单.
现在,在redux-form文档中,我读到我可以返回一个promise onSubmit以更新表单状态(submitting,error).但我不确定这样做的正确方法是什么.dispatch(login(formData))回报undefined.
我可以state.auth.pending在商店中用一个变量来交换标志,例如请求state.auth.status的值,成功和失败(再次,我可能会使用重新选择或类似的东西).
然后我可以订阅商店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
}
// ...
Run Code Online (Sandbox Code Playgroud)
但是,这个解决方案感觉并不好,我不确定当应用程序增长并且可能从其他来源发送更多操作时它是否总是按预期工作.
我看到的另一个解决方案是将api调用(返回一个promise)移动到onSubmit,但我想将它与React组件分开.
有什么建议吗?
Mic*_*ley 13
dispatch(login(formData))回报undefined
内部函数的任何返回值都将作为其
dispatch自身的返回值.
所以,你想要的东西
// 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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9019 次 |
| 最近记录: |