我是React生态系统的初学者,我正在使用React中的表单,构建一个包含两个字段的登录表单 - 电子邮件和密码 .
我在redux中维护我的整个表单状态 . 例如:
const defaultState = {
touched: { email: false, password: false },
loginFormErrors: {email: '', password: ''},
emailValid: false,
passwordValid: false,
formValid: false
}
其中一些状态值由 validateLoginFields
(reducer)更新,在调度VALIDATE_LOGIN_FIELDS操作时调用它们
const validateLoginFields = (state, action) => {
const newLoginFormErrors = {}
let emailValid = state.emailValid
let passwordValid = state.passwordValid
let formValid = state.formValid
switch(action.key) {
case 'email':
if(!action.value){
emailValid = false
newLoginFormErrors.email = ''
}else{
const pattern = new RegExp("[^\\s@]+@[^@\\s]+\\.[^@\\s]+")
emailValid = pattern.test(action.value)
newLoginFormErrors.email = emailValid ? '' : 'Invalid email'
}
break
case 'password':
if(!action.value){
passwordValid = false
newLoginFormErrors.password = ''
}else{
passwordValid = action.value.length >= 6
newLoginFormErrors.password = passwordValid ? '': 'Password is too short!';
}
break
default:
break
}
formValid = emailValid && passwordValid
const loginFormErrorData = {}
Object.assign(loginFormErrorData, state.loginFormErrors, newLoginFormErrors)
const newState = {}
Object.assign(newState, state, { loginFormErrors: loginFormErrorData, emailValid: emailValid, passwordValid: passwordValid, formValid: formValid })
return newState
}
我这里的问题很少:
-
我是否通过在Redux中维护我的表单的客户端验证详细信息(例如有效,触摸,formErrors等)来做正确的事情,或者我最好为此目的使用本地状态?因为我还在redux中存储auth相关数据,所以我觉得让Redux成为我所有事情的唯一真实来源感觉更舒服一点,但仍然希望与社区的其他人一起验证这个想法 .
-
是否可以像
validateLoginFields
这样的reducer函数执行客户端验证,就像我在我的示例中所示?它确实返回一个新的状态 - 这是reducer的功能,但是这个函数也在为我执行验证...我觉得这里有问题,可以用更好的方式完成 . 我的意思是更通用的验证? reducer是否适合像这样进行验证?
到目前为止,我正在努力进行客户端验证,似乎无法弄清楚如何以通用方式构建验证器,以便在应用程序变大时可以扩展它 . 非常感谢社区对此的任何想法 .
我确实尝试使用Redux-form和React-redux-form,这些库很棒,但我现在只想自己执行这些验证用于学习目的 .
UPDATE :
我将actionCreator改为看起来像这样,而不是在reducer中进行所有验证 . 我似乎无法弄清楚我应该在哪里以及如何以共享方式进行验证,以便我的应用程序中的其他电子邮件和密码字段可以访问此逻辑,而不仅仅是登录组件 .
export function validateLoginFields(key, value) {
const newLoginFormErrors = {}
let emailValid = false
let passwordValid = false
let formValid = false
switch(key) {
case 'email':
if(!value){
emailValid = false
newLoginFormErrors.email = ''
}else{
const pattern = new RegExp("[^\\s@]+@[^@\\s]+\\.[^@\\s]+")
emailValid = pattern.test(value)
newLoginFormErrors.email = emailValid ? '' : 'Invalid email'
}
break
case 'password':
if(!value){
passwordValid = false
newLoginFormErrors.password = ''
}else{
passwordValid = value.length >= 6
newLoginFormErrors.password = passwordValid ? '': 'Password is too short!';
}
break
default:
break
}
formValid = emailValid && passwordValid
return { type: VALIDATE_LOGIN_FIELDS, newLoginFormErrors, emailValid, passwordValid, formValid }
}
通过上述更改,即使我正在验证密码字段,我也将自己置于另一个问题中,即返回 emailValid=false
. 如果在我之前的状态 emailValid=true
那么它就变成了假 . 发生这种情况是因为我覆盖了我的状态值 . 有没有什么方法可以访问actionCreator中的当前状态,以便在没有任何更改的情况下返回相同的状态值?
但是,根据这篇文章,在行动中访问状态创造者不是最好的方式..
1 回答
我把我的验证放在我的Reducer中 . Reducers采用先前的状态和动作,然后返回一个新的状态 .
这是一个简单商店的结构:
这是一个更新客户并验证电子邮件地址的reducer:
(注意:这是伪代码 . 它从来没有被任何人运行过 . 它可以帮助你获得要点 . )
对我来说,reducer是进行验证的合理位置 . 他们认为,动作创建者的工作是发送更新商店所需的最小状态,而减速器的工作是将该状态转换为应用程序所需的最佳状态 . 我是那种认为验证是最佳的人,所以我在减速器中这样做 .