如何创建简单的多步骤登录并进行验证简介依赖关系让我们编写代码结论 PS

2025-06-08

如何创建带有验证的简单多步骤登录

介绍

依赖项

让我们开始编码

结论

聚苯乙烯

介绍

假设你需要创建一个类似 Gmail 的多步骤登录表单。你正在使用 React 和全局存储(Redux、Mobx)进行开发,并且希望将组件彼此隔离以便将来复用。此外,你还需要为每个步骤添加验证。在本文中,我将展示我认为最简单、最正确的解决方案。完整解决方案可以在这里查看。

依赖项

首先,我们需要一个用于处理表单的库。在我看来,最好的解决方案是 react-hook-forms ( https://react-hook-form.com/ ),该网站详细描述了为什么这是一个优秀的解决方案。我自己也补充一下,这个库功能强大(验证、快速集成、控制器机制)并且文档完善。
对于验证,我们将使用 yup 库,它是一个非常强大且流行的库。
对于全局存储,我将使用 little-state-machine,因为它是一个非常简单的解决方案,并且基于 flux 架构构建。当然,你也可以使用 redux 或 mobx。
要将 yup 验证模式与 react-hook-form 集成,你还需要 @hookform/resolvers 包。

让我们开始编码

项目结构

该示例使用以下项目结构

  • 步骤<-这里是所有表单步骤
    • Congrats.js <- 最后一步,如果登录成功
    • Email.js <- 第一步,输入邮箱继续登录
    • Password.js <- 第二步,输入密码登录
  • 店铺
    • actions.js <- 包括所有操作,在我的情况下只有一个用于更新表单状态
    • index.js <- 包括应用程序状态,在我的情况下只有表单状态
  • App.js <- 主要组件,在我的例子中包括表单逻辑
  • 指数
  • App.css <- 应用程序样式

关于商店

我们将在存储中存储表单步骤和电子邮件数据的信息。让我们在 store/index.js 中添加这些信息。

const state = {
  step: "Email",
  email: ""
};

export default state;
Enter fullscreen mode Exit fullscreen mode

现在让我们在 actions.js 中添加一个动作来更新表单

const updateFormState = (state, payload) => {
  return {
    ...state,
    ...payload
  };
};

export default updateFormState;

Enter fullscreen mode Exit fullscreen mode

让我们在 index.js 中将存储添加到应用程序中

import { StrictMode } from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { StateMachineProvider, createStore } from "little-state-machine";
import store from "./store";

// create out global form state
createStore(store);

const rootElement = document.getElementById("root");
ReactDOM.render(
  <StrictMode>
    <StateMachineProvider>
      <App />
    </StateMachineProvider>
  </StrictMode>,
  rootElement
);

Enter fullscreen mode Exit fullscreen mode

基本逻辑

表单切换的逻辑及其处理程序将在 App.js 中(仅供示例)。我们需要将 store 连接到组件,以便接收表单信息并进行更新。

import "./styles.css";
import { useStateMachine } from "little-state-machine";
import updateFormState from "./store/actions";
// Here we import form steps
import EmailStep from "./steps/Email";
import CongratsStep from "./steps/Congrats";
import PasswordStep from "./steps/Password";

export default function App() {
  // use hook for getting form state and actions
  const { state, actions } = useStateMachine({ updateFormState });
  // form handler for email step
  const emailFormHandle = ({ email }) => {
    actions.updateFormState({
      email: email,
      step: "Password"
    });
  };
  // form handler for password step
  const passwordFormHandle = ({ password }) => {
    actions.updateFormState({
      step: "Congrats"
    });
  };
  // sign out handler
  const signOutHandle = () => {
    actions.updateFormState({
      step: "Email"
    });
  };

  return (
    <div>
      {state.step === "Email" && (
        <EmailStep email={state.email} onSubmit={emailFormHandle} />
      )}
      {state.step === "Password" && (
        <PasswordStep onSubmit={passwordFormHandle} />
      )}
      {state.step === "Congrats" && (
        <CongratsStep email={state.email} onSignOut={signOutHandle} />
      )}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode


JavaScript
表单步骤组件尽可能彼此隔离,并可在应用程序的其他部分复用。您只需添加默认值(如果存在)(例如电子邮件步骤)和表单处理函数即可。

步骤

电子邮件

输入邮箱地址是用户授权的第一步。需要检查输入邮箱地址的有效性,并记住它,以防用户在输入密码的步骤中返回并稍作修改。这看起来可能有点牵强,但当表单中有大量输入时,保存它们的状态对于节省用户时间非常有用。代码及注释如下:

import { useForm } from "react-hook-form";
// import our validation library
import * as yup from "yup";
// import integration library
import { yupResolver } from "@hookform/resolvers/yup";
import cn from "classnames";

// validation schema
const Schema = yup.object().shape({
  // it says here that we want to check the input with the name email for the fact that the user will pass a string and this string matches email, you can change validation error message by changing text in email function argument
  email: yup.string().email("Enter valid email please")
});

const EmailStep = (props) => {
  // get form on Submit handler from parent component
  const { onSubmit, email } = props;
  // apply validations schema to react-hook-form form object
  const { errors, register, handleSubmit } = useForm({
    resolver: yupResolver(Schema),
    // if user input his email before we can paste it to input as default value
    defaultValues: {
      email
    }
  });

  //  you can check all validations errors in console
  console.log(errors);
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div className="form-group">
        <h2>Enter your email</h2>
      </div>
      <div className="form-group">
        {/* check validation errors */}
        {errors.email && (
          <h4 className="invalid-msg">{errors.email.message}</h4>
        )}
        <input
          // make input invalid if get email validation errors
          className={cn(errors.email && "input-invalid")}
          name="email"
          ref={register}
          placeholder="Your email"
        />
      </div>
      <div className="form-group">
        <button type="submit">Next</button>
      </div>
    </form>
  );
};

export default EmailStep;
Enter fullscreen mode Exit fullscreen mode

你需要知道的是:

  • 用户单击“提交”按钮(在我的情况下为“下一步”按钮)后将应用表单验证,但您可以在表单选项中更改此行为
  • 所有验证错误都包含在错误对象中,该对象由 react-hook-form 生成,其键为输入名称(email),值是验证信息(请输入有效的email)
  • 您可以通过 react-hook-form 表单对象使用默认的验证规则,无需任何库,但 yup 是更强大和灵活的包。

密码步骤

用户授权的最后一步。密码长度应大于6位,且包含​​拉丁字母。代码如下:

import { useForm } from "react-hook-form";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import cn from "classnames";

const Schema = yup.object().shape({
  password: yup
    .string()
    .min(6, "Password is too short")
    .matches(/[a-zA-Z]/, "Password can only contain Latin letters.")
});

const PasswordStep = (props) => {
  const { onSubmit } = props;
  const { errors, register, handleSubmit } = useForm({
    resolver: yupResolver(Schema)
  });

  console.log(errors);
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div className="form-group">
        <h2>Enter your password</h2>
      </div>
      <div className="form-group">
        {errors.password && (
          <h4 className="invalid-msg">{errors.password.message}</h4>
        )}
        <input
          className={cn(errors.password && "input-invalid")}
          name="password"
          type="password"
          ref={register}
          placeholder="Your password"
        />
      </div>
      <div className="form-group">
        <button type="submit">Sign In</button>
      </div>
    </form>
  );
};

export default PasswordStep;
Enter fullscreen mode Exit fullscreen mode

最后一步

最后让我们向用户显示祝贺消息

const CongratsStep = (props) => {
  const { email, onSignOut } = props;

  return (
    <div className="form-group">
      <h2>
        Hello, {email}
        <button onClick={onSignOut}>Sign Out</button>
      </h2>
      <img src="https://i.giphy.com/6nuiJjOOQBBn2.gif" alt="" />
    </div>
  );
};

export default CongratsStep;
Enter fullscreen mode Exit fullscreen mode

结论

就这样。我们创建了独立的表单步骤,为邮箱地址添加默认值,为每个表单步骤添加验证规则,并使用了我们最强大、最流行的软件包(除了 little-state-machine)。
如果您感兴趣,我可以用 TypeScript、MUI 和 Mobx 或 Redux 软件包来演示这些示例。

聚苯乙烯

这是我的第一篇文章,英语不是我的母语,希望一切都清楚,你度过了愉快的时光:)如果你在理解文本方面有问题(因为我不太了解该语言),你可以随时查看我的代码,它比任何文字都更有说服力

鏂囩珷鏉ユ簮锛�https://dev.to/alex1998dmit/how-to-create-simple-many-step-form-with-validation-3g4f
PREV
掌握 TypeScript:使用类型循环
NEXT
✨ 可访问性:简单介绍 ✨ 定义