【问题标题】:Form states in react reduxreact redux 中的表单状态
【发布时间】:2017-11-14 02:13:12
【问题描述】:

我是 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
}

我有几个问题:

  1. 通过在 Redux 中维护表单的客户端验证详细信息(例如有效、已触摸、formErrors 等),我是否在做正确的事情,或者我更适合为此目的使用本地状态?由于我还在 redux 中存储了与身份验证相关的数据,因此将 Redux 作为我所有事情的唯一真实来源让我感觉更舒服一些,但仍然想与社区的其他人一起验证这个想法。

  2. validateLoginFields 这样的reducer 函数是否可以像我在示例中显示的那样执行客户端验证?它确实返回了一个新状态——这是减速器所做的,但这个函数也在为我执行验证......我觉得这里出了点问题,可以用更好的方式完成......我的意思是更通用的验证? reducer 是否适合进行此类验证?

到目前为止,我一直在努力进行客户端验证,并且似乎无法弄清楚我应该如何以通用方式构建我的验证器,以便在我的应用程序变大时可以对其进行扩展。将非常感谢社区对此的任何想法。

我确实尝试过使用 Redux-form 和 React-redux-form ,这些库很棒,但我现在只想自己执行这些验证以用于学习目的。

更新:

我将 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 中的当前状态,以便在没有任何变化的情况下返回相同的状态值?

但是,根据这篇文章,访问 actionCreator 中的状态并不是最好的方法..

Accessing Redux state in an action creator?

【问题讨论】:

  • 我会将验证放在 actionCreator() 中。通常,reducer 只是将一个新状态作为参数,什么都不做

标签: reactjs ecmascript-6 redux create-react-app react-redux-form


【解决方案1】:

我把我的验证放在我的减速器中。 Reducers 接受之前的状态和一个动作,然后返回一个新的状态。

这是一个简单商店的结构:

{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 是进行验证的合乎逻辑的地方。我认为他们的方式是动作创建者的工作是发送更新商店所需的最小状态,而reducer的工作是将该状态转换为最佳应用程序所需的状态。我是那种认为验证是最佳的人,所以我在我的 reducer 中这样做。

【讨论】:

  • 这很酷。 redux-form 的替代方案要复杂得多。
  • 这对我来说看起来并不理想。验证将在对服务器的任何调用之后发生:我们将 AJAX 调用放在 ActionCreators(异步)中,它们位于 Redux Flow 中的 Reducer 之前 - 通常应该进行验证在任何 AJAX 请求之前。
猜你喜欢
  • 2018-07-17
  • 2020-12-11
  • 2021-08-04
  • 2018-05-02
  • 2017-08-18
  • 2019-02-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-08
相关资源
最近更新 更多