美文网首页
react-hook-form使用

react-hook-form使用

作者: 朱传武 | 来源:发表于2021-06-23 18:56 被阅读0次

    官网地址:https://react-hook-form.com/
    react-hook-form是专门为校验表单、提交表单设计的,使用起来比传统的onChange、setState要方便很多。
    而且它进一步做了优化,减少了不必要的render

    image.png

    安装

    npm install react-hook-form
    

    使用

    import React from "react";
    import { useForm, SubmitHandler } from "react-hook-form";
    
    type Inputs = {
      example: string,
      exampleRequired: string,
    };
    
    export default function App() {
      const { register, handleSubmit, watch, formState: { errors } } = useForm<Inputs>();
      const onSubmit: SubmitHandler<Inputs> = data => console.log(data);
    
      console.log(watch("example")) // watch input value by passing the name of it
    
      return (
        /* "handleSubmit" will validate your inputs before invoking "onSubmit" */
        <form onSubmit={handleSubmit(onSubmit)}>
          {/* register your input into the hook by invoking the "register" function */}
          <input defaultValue="test" {...register("example")} />
          
          {/* include validation with required or other standard HTML validation rules */}
          <input {...register("exampleRequired", { required: true })} />
          {/* errors will return when field validation fails  */}
          {errors.exampleRequired && <span>This field is required</span>}
          
          <input type="submit" />
        </form>
      );
    }
    

    我们项目中的使用

    export default function AddressForm({ className }: AddressFormProps): React.ReactElement {
      const {
        formState: { errors },
        register,
      } = useContext(UseFormContext) as UseFormReturn;
    
      return (
        <div className={classnames("space-y-6", className)}>
          <Input
            placeholder="Address Name (ex. home)*"
            register={register("addressName", { required: "Address name is required" })}
            {...useFormProps({ name: "addressName", errors })}
          />
          <Input
            placeholder="Street Name*"
            register={register("streetName", { required: "Street Name is required" })}
            {...useFormProps({ name: "streetName", errors })}
          />
          <div className="grid grid-cols-2 gap-x-2 gap-y-6">
            <Input
              placeholder="Street Number*"
              register={register("streetNumber", { required: "Street Number is required" })}
              {...useFormProps({ name: "streetNumber", errors })}
            />
            <Input
              placeholder="Flat, Floor, Door"
              register={register("flat", { required: "Flat, Floor, Door is required" })}
              {...useFormProps({ name: "flat", errors })}
            />
            <Input
              placeholder="City*"
              register={register("city", { required: "City is required" })}
              {...useFormProps({ name: "city", errors })}
            />
            <Select
              options={states}
              placeholder={stateSelectPlaceHolder}
              register={register("state", { required: "State is required" })}
              {...useFormProps({ name: "state", errors })}
            />
            <Input
              placeholder="PinCode*"
              register={register("pinCode", { required: "Pin Code is required" })}
              {...useFormProps({ name: "pinCode", errors })}
            />
            <Input
              placeholder="Country*"
              register={register("Country", { required: "Country is required" })}
              {...useFormProps({ name: "country", errors })}
            />
            <Input
              placeholder="LandMark*"
              register={register("landMark", { required: "LandMark is required" })}
              {...useFormProps({ name: "landMark", errors })}
            />
          </div>
          <Toggle label={<span className="body">Set as default address</span>} />
        </div>
      );
    }
    
     body={
            <>
              <UseFormContext.Provider value={useFormMethods}>
                <AddressForm className="mt-4" />
              </UseFormContext.Provider>
              <div className="hidden md:block md:mt-10">
                <CustomButton noMargin fullSize rounded primary label="SAVE" onClick={onSubmit} />
              </div>
            </>
          }
    
    const onSubmit = useMemo(
        () =>
          handleSubmit(async (data) => {
            // TODO: Call API
            // eslint-disable-next-line no-console
            debugger;
            console.log(data);
            if (nextStepHref) {
              await router.push(nextStepHref);
              switch (nextStepHref.pathname) {
                case pathnames.settingsAddressTab:
                  showNotifications({
                    type: "default",
                    title: "Address Changed",
                    message: "You have successfully changed your address.",
                  });
                  break;
                default:
                  break;
              }
            }
          }),
        [handleSubmit, nextStepHref, router, showNotifications]
      );
    

    完全替代了原先需要在组件里面声明state来接受input的值。

    监听功能

    import React from "react";
    import { useForm } from "react-hook-form";
    
    function App() {
      const { register, watch, formState: { errors }, handleSubmit } = useForm();
      const watchShowAge = watch("showAge", false); // you can supply default value as second argument
      const watchAllFields = watch(); // when pass nothing as argument, you are watching everything
      const watchFields = watch(["showAge", "number"]); // you can also target specific fields by their names
    
      const onSubmit = data => console.log(data);
    
      return (
        <>
          <form onSubmit={handleSubmit(onSubmit)}>
            <input type="checkbox" {...register("showAge")} />
            
            {/* based on yes selection to display Age Input*/}
            {watchShowAge && <input type="number" {...register("age", { min: 50 })} />}
            
            <input type="submit" />
          </form>
        </>
      );
    }
    

    单独组件监听

    import React from "react";
    import { useForm, useWatch } from "react-hook-form";
    
    function IsolateReRender({ control }) {
      const firstName = useWatch({
        control,
        name: 'firstName', // without supply name will watch the entire form, or ['firstName', 'lastName'] to watch both
        defaultValue: 'default' // default value before the render
      });
    
      return <div>{firstName}</div>; // only re-render at the component level, when firstName changes
    }
    
    function App() {
      const { register, control, handleSubmit } = useForm();
      
      return (
        <form onSubmit={handleSubmit(data => console.log("data", data))}>
          <input {...register("firstName")} />
          <input {...register("last")} />
          <IsolateReRender control={control} />
          
          <input type="submit" />
        </form>
      );
    

    默认值

    很多时候,我们需要设置默认值,比如在编辑的时候,已经有原有的值了,这个时候怎么设置呢?

    const useFormMethods = useForm<AddressInfo>({
        defaultValues: {
          streetAddress1: "dfsdds",
          villageArea: "dfds",
          houseNumber: "fsdf",
          flat: "fdsdf",
          townCity: "fdsd",
          provinceState: "China",
          pinCode: "dsffsd",
          country: "dffds",
          landMark: "fdsfds",
        },
      });
    

    useFormContext 使用

    表单在一个子组件里面,这时候就要用useFormContext了,
    父组件:

    import { useForm, FormProvider } from "react-hook-form";
    
    const useFormMethods = useForm<AddressInfo>({
        defaultValues: {
          streetAddress1: "dfsdds",
          villageArea: "dfds",
          houseNumber: "fsdf",
          flat: "fdsdf",
          townCity: "fdsd",
          provinceState: "China",
          pinCode: "dsffsd",
          country: "dffds",
          landMark: "fdsfds",
        },
      });
    
     <FormProvider {...useFormMethods}>
                <AddressForm className="mt-4" onDefaultAddressChange={onDefaultAddressChange} />
              </FormProvider>
    

    通过FormProvider 把useFormMethods传递给子组件
    子组件接收使用:

    import { useFormContext } from "react-hook-form";
    
     const {
        formState: { errors },
        register,
      } = useFormContext();
    
    <Input
            placeholder="Address Name (ex. home)*"
            register={register("streetAddress1", { required: "Address name is required" })}
            {...useFormProps({ name: "streetAddress1", errors })}
          />
    

    官方demo也挺好:

    import React from "react";
    import { useForm, FormProvider, useFormContext } from "react-hook-form";
    
    export default function App() {
      const methods = useForm();
      const onSubmit = data => console.log(data);
    
      return (
        <FormProvider {...methods} > // pass all methods into the context
          <form onSubmit={methods.handleSubmit(onSubmit)}>
            <NestedInput />
            <input type="submit" />
          </form>
        </FormProvider>
      );
    }
    
    function NestedInput() {
      const { register } = useFormContext(); // retrieve all hook methods
      return <input {...register("test")} />;
    }
    

    官方demo地址 https://github.com/react-hook-form/react-hook-form/tree/master/examples

    相关文章

      网友评论

          本文标题:react-hook-form使用

          本文链接:https://www.haomeiwen.com/subject/uzabyltx.html