Reactjs react-redux中的形式状态
我是React生态系统的初学者,我正在尝试React中的表单,创建一个包含两个字段的登录表单-电子邮件和密码 我在redux中维护我的整个表单状态。例如:Reactjs react-redux中的形式状态,reactjs,ecmascript-6,redux,create-react-app,react-redux-form,Reactjs,Ecmascript 6,Redux,Create React App,React Redux Form,我是React生态系统的初学者,我正在尝试React中的表单,创建一个包含两个字段的登录表单-电子邮件和密码 我在redux中维护我的整个表单状态。例如: const defaultState = { touched: { email: false, password: false }, loginFormErrors: {email: '', password: ''}, emailValid: false, passwordValid: false,
const defaultState = {
touched: { email: false, password: false },
loginFormErrors: {email: '', password: ''},
emailValid: false,
passwordValid: false,
formValid: false
}
其中一些状态值由validateLoginFields
(reducer)更新,在调度VALIDATE\u LOGIN\u 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
}
我这里有几个问题:
validateLoginFields
这样的reducer函数执行我在示例中所示的客户端验证是否合适?它确实返回了一个新的状态-这是一个reducer所做的,但是这个函数也在为我执行验证。。。我觉得这里有些地方不对劲,可以用更好的方法来做。我是说更普遍的验证?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则变为false。这是因为我覆盖了我的状态值。是否有任何方法可以访问actionCreator中的当前状态,以便在没有任何更改的情况下返回相同的状态值
但是,根据这篇文章,在actionCreator中访问状态并不是最好的方式
我将验证放在我的还原器中。还原程序执行以前的状态和操作,然后返回新状态 以下是一个简单商店的结构:
{customer: {
firstName: "FatBoy",
lastName: "Slim",
email: 'foo@bar.com',
validationErrors: {}
}}
以下是一个reducer,它更新客户并验证电子邮件地址:
function customerReducer(state = {}, action) {
switch (action.type) {
case 'UPDATE_CUSTOMER':
let validationErrors = {}
let emailError = validateEmail(action.customer.email);
if (emailError) {
validationErrors['email'] = emailError;
}
return {...state, ...action.customer, validationErrors};
default:
return state;
}
}
(注意。这是伪代码。从来没有人运行过它。您可以从中获得要点。)
对我来说,减速机是进行验证的合理场所。在我看来,操作创建者的任务是发送更新存储所需的最小状态,而reducer的任务是将该状态转换为应用程序所需的最佳状态。我是那种认为验证是最优的人,所以我在我的简化程序中这样做。我会将验证放在actionCreator()中。通常,减缩器只是把一个新的状态作为参数,不做更多的事情。这很酷。redux表单的替代方案要复杂得多。这在我看来并不理想。验证将在对服务器的任何调用之后进行:我们将AJAX调用放在ActionCreators(异步)中,它们位于redux流中的Reducer之前——通常验证应该在任何AJAX请求之前完成。