简体   繁体   English

当 onSubmit 调用时,react-hook-form 不起作用

[英]react-hook-form not working when onSubmit called

I'm trying to have react forms save and then update some user settings.我正在尝试保存反应表单,然后更新一些用户设置。

import React, { useState, useEffect } from "react";
import Dropdown from "components/Settings/Preferences/Dropdown";
import { useForm } from "react-hook-form";

function Pill({ value, handleChange,optionName,substanceKey,key }) {
    return (
      <div  className="bg-gray-600 text-white text-xs px-2 py-0.5 w-max-content rounded-lg align-middle mr-1 mb-1">
        {value}
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
          className="inline-block align-middle cursor-pointer"
          onClick={() => handleChange(value, "remove",optionName,substanceKey)}
        >
          <line x1="18" y1="6" x2="6" y2="18" />
          <line x1="6" y1="6" x2="18" y2="18" />
        </svg>
      </div>
    );
  }

function InventoryPage(props) {
    const [substanceDetails, setSettings] = useState(
        [
          {
            substance: "Modafinil",
            scheduledtimes: [8, 13],
            startdate: "1996-12-02",
            enddate: "2020-01-01",
            duration: 2,
            planneddose: "10mg"
          },
          {
            substance: "Coveve",
            scheduledtimes: [8, 12],
            startdate: "1996-12-02",
            enddate: "2020-01-01",
            duration: 2,
            planneddose: "10mg"
          }
      );


      const { register, handleSubmit,watch, errors,formState } = useForm();
      const handleChange = (value, mode,optionName,substanceKey) => {
        var removedSubstances ;
        if(mode==="remove") {
          if (optionName === "substance" ) {
            removedSubstances = substanceDetails.find(v=> v.substance === value) ? substanceDetails.filter(v => v.substance !== value) : [...substanceDetails, value]
          }
         
       else {
          removedSubstances = substanceDetails.reduce((acc, key) => {
      //  return acc; // remove keys
        if (optionName === "scheduledtimes") { //works
          // remove 14 in times for keys
          return [...acc, { ...key,
            scheduledtimes: key.scheduledtimes.filter(time => time !== value)
          }]
        }
        if (optionName === "planneddose") {
          // modify the power by concatenating an new object with partial info
          if (key.substance == substanceKey){
      
          return [...acc, {...key,
            planneddose: null
          }];
        } else {
          return [...acc, {...key,
            planneddose: key.planneddose
          }];
        }
        }
      
        if (optionName === "startdate") {
          // modify the power by concatenating an new object with partial info
          if (key.substance == substanceKey){
      
          return [...acc, {...key,
            startdate: null
          }];
        } else {
          return [...acc, {...key,
            startdate: key.startdate
          }];
        }
        }
        if (optionName === "enddate") {
          // modify the power by concatenating an new object with partial info
          if (key.substance == substanceKey){
      
          return [...acc, {...key,
            enddate: null
          }];
        } else {
          return [...acc, {...key,
            enddate: key.enddate
          }];
        }
        }
      
        if (optionName === "duration") {
          // modify the power by concatenating an new object with partial info
          if (key.substance == substanceKey){
      
          return [...acc, {...key,
            duration: null
          }];
        } else {
          return [...acc, {...key,
            duration: key.duration
          }];
        }
        }
        
      }
      , []);
       }
      setSettings(removedSubstances)
        }
      };
  const onSubmit = data => console.log(data);
  const [pending, setPending] = useState(false);
  
   
  console.log(watch("example")); // watch input value by passing the name of it

  if (substanceDetails === false) {
    return (
      <div className="md:grid md:grid-cols-3 md:gap-6">
        <div className="md:col-span-1">
          <h3 className="text-lg font-medium leading-6 text-gray-900">
            Substances
          </h3>
        </div>
        <div className="mt-5 md:mt-0 md:col-span-2 font-mono font-medium text-blue-500">
          loading...
        </div>
      </div>
    );
  }
  

  return (
    <div className="md:grid md:grid-cols-3 md:gap-6">

    <div className="mt-5 md:mt-0 md:col-span-2">
     <form onSubmit={handleSubmit(onSubmit)} id="formName">
          <div className="flex flex-wrap mt-2">
            {substanceDetails &&
              substanceDetails.map((subst) => (
                <Pill
                  registerInput={register}
                  optionLabel="substance"
                  value={subst.substance}
                  key={subst.substance}
                  substanceKey = {subst.substance}
                  optionName={"substance"}
                  // allOptions={["Dexamphetamine", "Ritalin"]}
                  handleChange={handleChange}
                  error={formState.errors?.content ? true : false}
                />
              ))}
          </div>
          <Dropdown
            registerInput={register}
            optionLabel="Substance"
            selectedOption={substanceDetails.substance}
            optionName={"substance"}
            allOptions={["Dexamphetamine", "Ritalin"]}
            error={formState.errors?.content ? true : false}
          />
          <button
            className="inline-flex items-center justify-center px-5 py-2 border border-transparent text-base leading-6 font-medium rounded-md text-indigo-700 bg-indigo-100 hover:text-indigo-600 hover:bg-indigo-50 focus:outline-none focus:shadow-outline focus:border-indigo-300 transition duration-150 ease-in-out"
            variant={props.buttonColor}
            size={props.inputSize}
            type="submit"
            disabled={pending}
            form="formName"

          >
            {pending ? (
              <>
                <span>Saving</span>
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 24 24"
                  className="animate-spin h-4 w-4 ml-3 fill-current"
                >
                  <path d="M0 11c.511-6.158 5.685-11 12-11s11.489 4.842 12 11h-2.009c-.506-5.046-4.793-9-9.991-9s-9.485 3.954-9.991 9h-2.009zm21.991 2c-.506 5.046-4.793 9-9.991 9s-9.485-3.954-9.991-9h-2.009c.511 6.158 5.685 11 12 11s11.489-4.842 12-11h-2.009z" />
                </svg>
              </>
            ) : (
              <span>Save</span>
            )}
          </button>
        </form>
    </div>
    </div>
  );
}

export default InventoryPage;

Currently when hitting submit, the form itself is just refreshing the page, and it's not using the onSubmit constant.目前,当点击提交时,表单本身只是刷新页面,而不是使用 onSubmit 常量。 I'm not sure what's going on, love some help :)我不确定发生了什么,喜欢一些帮助:)

Sandbox link, code is compiling but probably easier to vet the code itself沙盒链接,代码正在编译但可能更容易审查代码本身

https://codesandbox.io/s/using-tailwind-with-nextjs-forked-nnr0l?file=/pages/index.js https://codesandbox.io/s/using-tailwind-with-nextjs-forked-nnr0l?file=/pages/index.js

You are calling onSubmit inside handleSubmit.您正在 handleSubmit 内调用 onSubmit。 Remove that and I feel your code will work fine.删除它,我觉得你的代码会正常工作。

Try using the id attribute on the form tag, ie尝试使用表单标签上的 id 属性,即

<form onSubmit={handleSubmit(onSubmit)} id="formName">

And on the button tag, you use the form attribute which will be the same as the form id, ie在按钮标签上,您使用与表单 ID 相同的表单属性,即

<button 
  variant={props.buttonColor} 
  size={props.inputSize} 
  type="submit" 
  disabled={pending}
  form="formName"
>

if nothing works, from above suggestions.如果没有任何效果,从上面的建议。

use preventDefault for submit使用 preventDefault 提交

and handle submit with a different function , get all the data you need using document.getElement or querySelector and handle them in the function.并使用不同的函数处理提交,使用 document.getElement 或 querySelector 获取您需要的所有数据,并在函数中处理它们。

Please take a look at this example https://codesandbox.io/s/using-tailwind-with-next-js-forked-tizjq?file=/pages/index.js请看一下这个例子https://codesandbox.io/s/using-tailwind-with-next-js-forked-tizjq?file=/pages/index.js

After required fields are filled submit button is clicked, form submits填写必填字段后点击提交按钮,表单提交

Your CodeSandbox link wouldn't compile for me, but take a look at this discussion on the RHF github about how to prevent form submission in the submit handler.您的 CodeSandbox 链接不会为我编译,但请查看 RHF github 上有关如何防止提交处理程序中提交表单的 讨论 It's involving async stuff but should be similar for your needs.它涉及异步内容,但应该与您的需求相似。 I think you just need to pass the event and preventDefault as others have said, and maybe their example will be worth following.我认为你只需要像其他人所说的那样传递事件和 preventDefault ,也许他们的例子值得效仿。

而不是按钮尝试使用 type="submit" 的输​​入元素并设置它的样式

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM