javascript 如何使用setState挂接验证响应中用户输入

zfciruhq  于 2023-02-18  发布在  Java
关注(0)|答案(3)|浏览(138)

我有一个表单。在表单中,我从用户那里得到brandName,supplierName和过期日期。我使用来自mui库的TextField和提交按钮。我想禁用空表单字段上的提交按钮,并在用户填写所有输入时启用它。这里是我声明useStates的代码

const[brandName, setBrandName] = useState("");
       const[supplierName, setSupplierName] = useState("");
       const[expiryDate, setExpiryDate] = useState(null);
       const[brandNameError, setBrandNameError] = useState(false);
       const[supplierNameError, setSupplierNameError] = useState(false);
       const[expiryDateError, setExpiryDateError] = useState(false);

       const[submitButton, setSubmitButton] = useState(true);

这是我用来验证输入的所有函数

// checking brandName Error
        const brandNameValidateOnBlur = ()=>{
          if(brandName === ""){
            setBrandNameError(true);
          }
       }

       // checking supplier name error
       const supplierNameValidateOnBlur = ()=>{
        if(supplierName === ""){
            setSupplierNameError(true);
        }
       }
       // checking expiry date
       const expiryDateValidateOnBlur = ()=>{
        if(expiryDate === ""){
            setExpiryDateError(true);
        }
       }
 
        // now checking all inputs again if all inputs are good then
        // button should be enabled 

        const checkAllInputs = ()=>{
            if(brandName !== "" && supplierName !== "" && expiryDate !== ""){
                setSubmitButton(false);
            }else{
                setSubmitButton(true);
            }
        }

这是剩下的代码

<TextField  fullWidth id="productName" label="Product Name" 
        value={brandName.toLowerCase()} variant="outlined" 
      onChange={(data)=>{setBrandName(data.target.value.toUpperCase());checkAllInputs()}}
      onBlur={brandNameValidateOnBlur}
      onFocus={()=>setBrandNameError(false)}
      error={brandNameError}
      helperText = {brandNameError ? "Enter Brand Name" : ""}
      />
      <TextField id="supplierName"  
      label="Supplier Name" 
      value={supplierName.toLowerCase()} variant="outlined"
      onBlur={supplierNameValidateOnBlur}
      onFocus={()=>setSupplierNameError(false)}
      error={supplierNameError}
      helperText={supplierNameError ? "Enter Supplier Name " : ""}
      onChange={(data)=>{setSupplierName(data.target.value.toUpperCase());checkAllInputs()}} />
      <LocalizationProvider dateAdapter={AdapterDayjs}>
      <DesktopDatePicker
          label="Date Expiry"
          inputFormat="MM/DD/YYYY"
          value={expiryDate}
          onBlur={expiryDateValidateOnBlur}
          onFocus={()=>setExpiryDateError(false)}
          error={expiryDateError}
          helperText={expiryDateError ? "Enter Expiry Date ": ""}
          onChange={(selectedDate)=>
          {setExpiryDate(selectedDate.format("MM/DD/YYYY"));checkAllInputs()}}
          renderInput={(params) => <TextField {...params} />}
        />
     </LocalizationProvider>
      <Button type='button' variant='contained' id="submitButton" disabled={submitButton}
      style={{backgroundColor:'orangered'}} onClick={addData}>Add Data</Button>

现在的问题是,当我输入一个单词时,我的useState更新,但我的checkAllInputs不工作,因为我想这样,如果我输入一个单词,我的checkAllInputs方法在设置状态之前运行,因为我输入第二个条目,然后它像我想这样工作,所以我不知道我做错了什么
我试着用这样的效果钩

useEffect(()=>{
        checkAllInputs();
       },[brandName, supplierName, expiryDate]);

它的工作很好,因为我接受了,但我读到它应该是一个昂贵的使用效果
我用的另一种方法

const checkAllInputsWithDom = ()=>{
         let brandNameEntry = document.getElementById("brandName").value;
         let supplierNameEntry = document.getElementById("supplierName").value;
         let expiryDateEntry = document.getElementById("expiryDate").value;
         if(brandNameEntry !=="" && supplierNameEntry !== ""  && expiryDateEntry !== ""){
            setSubmitButton(false);
         }else{
            setSubmitButton(true);
         }
      }

它是工作的开箱即用,但我的事情在React,这是违反React原则,以直接操纵圆顶元素,我可以这样做与出使用useeffect挂钩一样,只有与我的metohd和一件事,这没有设置expiryDate错误的日期字段

jvlzgdj9

jvlzgdj91#

只要你保持输入值在状态中,你就不需要另一个变量来存储按钮状态。你可以在渲染时计算它。(阅读更多关于避免冗余状态的信息。
你可以这样做:

const Component = () => {
  const[brandName, setBrandName] = useState("");
  const[supplierName, setSupplierName] = useState("");
  const[expiryDate, setExpiryDate] = useState("");

  const disabled = brandName.length === 0 && supplierName.length === 0 && expiryDate.length === 0

  return (
    <>
      <input value={brandName} onChange={(e) => setBrandName(e.target.value)}/>
      <input value={supplierName} onChange={(e) => setSupplierName(e.target.value)}/>
      <input value={expiryDate} onChange={(e) => setExpiryDate(e.target.value)}/>
      <button disabled={disabled}>Button</button>
    </>
  )
}
vojdkbi0

vojdkbi02#

这是link for codesandbox我建议您重构这6个使用状态,其中只有一个useState作为一个对象,其所有值如下所示:

const initialValues = {
  brandName: "",
  supplierName: "",
  expiryDate: "",
  brandNameError: "",
  supplierNameError: "",
  expiryDateError: ""
};

然后使用如下所示的通用handleInputChange对其进行更新:

const handleInputChange = (e) => {
    //const name = e.target.name
    //const value = e.target.value
    const { name, value } = e.target;

    setValues({
      ...values,
      [name]: value
    });
    let isEmpty = Object.values(values).some((x) => x === "");
    console.log(isEmpty);
    setIsDisabled(isEmpty);
  };

为您提供解决方案

你只需要检查所有的值,然后用isDisabled创建一个布尔值,这样当所有的值都为空时,它只会设置为false。
我已经为您创建了一个代码片段,它需要一些改进,但它将服务于您的目的。链接已经在顶部和here以及

dzjeubhm

dzjeubhm3#

正如Eduardo Motta de Moraes所建议的,我使用此命令在所有输入验证后启用按钮

const disabled= brandName.length === 0 || supplierName.length === 0 || expiryDate.length === 0;

这解决了我的问题,谢谢爱德华多·莫塔·德·莫赖斯

相关问题