【问题标题】:Splitting Credit Card Expiration Date onChange拆分信用卡到期日期 onChange
【发布时间】:2021-12-01 19:11:06
【问题描述】:

所以我需要在我的 formData 中将信用卡到期日期拆分为两个单独的值。

这是我如何设置组件。

const [ formData, setFormData ] = useState({
email: '',
password: '',
username: '',
card_num: '',
cvv_code: '',
cc_exp: '',
cc_exp_year: '',
cc_exp_month,
first_name: '',
last_name: '',
    })

我也在这里解构所有的formData:

const { email, password, username, card_num, cvv_code, cc_exp, cc_exp_year, cc_exp_month, first_name, last_name } = formData;

我在这里有我的 onChange 函数:

const onChange = e =>  {
setFormData({ ...formData, [e.target.name]: e.target.value })
  }

一个

当我输入 cc_exp 的到期日期时,我得到了正确的 MM/YY 格式,但我需要将值拆分为 cc_exp_month 和 cc_exp_year。所以我的问题是,在 / 处拆分字符串的最佳位置在哪里,然后如何将它们添加到 formData 中的这些值中。

我已经尝试在 onSubmit 函数中使用 setFormData 来简单地在事后添加值:

const onSubmit = e => {
        e.preventDefault();
        setFormData(formData => ({
            ...formData,  // shallow copy previous state
            cc_exp_month: cc_exp.split('/')[0], // add new property values
            cc_exp_year: cc_exp.split('/')[1],
            username: email
          }));
        dispatch(createMembership(formData, id));
    }

我认为在我发送数据之前最好的方法是 onSubmit。这样我就不必将函数链接在一起,因为我真的不确定在哪里添加它。因此,在设置 cc_exp 并且所有表单数据都存在之后,我试图拆分该值,然后在提交数据之前将其应用于这些其他值 cc_exp_month 和 cc_exp_year。但是当我点击提交时,月份和年份不显示。但是,如果我要单击提交两次(没有人会这样做),那么数据会在 formData 中正确显示。所以它就像 setFormData 一样不想在 onSubmit 中添加新的 exp 数据。

【问题讨论】:

    标签: reactjs react-hooks use-state


    【解决方案1】:

    当您将多个更新排入队列时,例如

    setFormData({...formData,  cc_exp_month : cc_exp.split('/')[0] })
    setFormData({...formData,  cc_exp_year : cc_exp.split('/')[1] })
    

    每个都使用相同的未更新的formData 值并覆盖之前排队的更新。从以前的状态更新时,您应该使用功能状态更新。如果没有单个更新更新需要以前的临时更新,您还可以将所有更新合并为一个更新。使用数组解构赋值创建cc_exp_monthcc_exp_year变量,然后在返回的状态值中使用对象简写赋值。

    const [cc_exp_month, cc_exp_year] = cc_exp.split('/');
    
    setFormData(formData => ({
      ...formData,  // shallow copy previous state
      cc_exp_month, // add new property values
      cc_exp_year,
    }));
    

    更新

    React 状态更新是异步处理的,因此拆分 CC 到期并将状态更新入队不会立即更新 formData。请参阅此 answer 并附上解释。

    const onSubmit = e => {
      e.preventDefault();
      setFormData(formData => ({ // <-- returns state for next render cycle
        ...formData, 
        cc_exp_month: cc_exp.split('/')[0],
        cc_exp_year: cc_exp.split('/')[1],
        username: email
      }));
      dispatch(createMembership(formData, id)); // <-- state from this render cycle
    }
    

    你有几个选择:

    1. 使用useEffect 挂钩来更新cc_exp_monthcc_exp_year 属性,特别是在formData.cc_exp 属性更新时。

      useEffect(() => {
        setFormData(formData => {
          const [cc_exp_month, cc_exp_year] = formData.cc_exp.split('/');
          return {
            ...formData,
            cc_exp_month,
            cc_exp_year,
          }
        });
      }, [formData.cc_exp]);
      

      谨慎使用此方法,因为通常要避免更新useEffect 回调中可能存在于效果依赖数组中的任何内容。 不要更新 formData.cc_exp 值,因为这会创建渲染循环!!

    2. 计算您要在提交处理程序中提交的表单数据对象,并且不必费心在状态中存储本质上是重复的数据,因为已经存在formData.cc_exp 状态。

      const onSubmit = e => {
        e.preventDefault();
      
        const [cc_exp_month, cc_exp_year] = formData.cc_exp.split('/');
      
        const data = {
          ...formData,
          cc_exp_month,
          cc_exp_year,
        };
      
        dispatch(createMembership(data, id));
      }
      

      在我看来,第二个选项将是首选方法,因为它具有较少的移动部件并避免了无关的状态更新和重新渲染。 cc_exp_monthcc_exp_year很容易从状态派生出来,派生出来的状态不属于状态。

    【讨论】:

    • 此解决方案仅适用于第二次 onSubmit 点击。由于某种原因,它没有在第一次点击时设置新值。关于为什么会发生这种情况的任何见解?
    • @KelleyMuro 你为什么要点击两次提交?这没有任何意义。在您的问题中提交任何内容也没有任何意义,因此任何人都可以猜测提交正在做什么。提交是否与您拆分 CC 到期字符串的问题相关?如果是,请更新问题以包含所有相关详细信息,如果不是,请检查此处的答案是否解决了当前问题并发布有关任何表单提交的新问题。 (如果您这样做,请随时在此处 ping (@me) 并附上新帖子的链接
    • 如果onSubmit中没有设置cc_exp信息后,我在哪里可以设置表单数据?
    • @KelleyMuro 上面的代码在提交处理程序中吗?您能否澄清一下您尝试将状态更新排入队列的时间和地点,以便我们更清楚地了解代码试图做什么?您可以使用新的相关详细信息编辑您的问题。
    • 非常感谢您迄今为止的帮助。我已经编辑了我的问题。
    【解决方案2】:

    formData 的新更新值不能被第二次调用 setFormData 计数,因为钩子是异步的。您可能想尝试使用两个新值调用一次setFormData()

    setFormData({
      ...formData,
      cc_exp_month: cc_exp.split('/')[0],
      cc_exp_year: cc_exp.split('/')[1]
    })
    

    【讨论】:

    • 这适用于第二次点击 onSubmit。出于某种原因,当我第一次提交它时,状态未设置拆分值。但如果我再次单击它,它将起作用。我不知道为什么。
    猜你喜欢
    • 2023-03-18
    • 2019-10-16
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    相关资源
    最近更新 更多