reactjsvalidationreact-hooksfluentui-react

How to avoid validation on clearing values from the textfield in react


I have a question regarding validation of inputs. I'm using Fabric UI for the textfields, which have onGetErrorMessage, which I'm using to validate input. The textfield is a controlled element. It is all working well, except one moment, when I do a reset / clear of the fields, it triggers the validation and then I get error messages, saying cannot be empty, which is fine due to the validation, but not fine if we are talking about reset.

I'll post here parts of the code which I use.

const els: React.ReactElement[] = [];

els.push(<ChoiceGroup label = "Choice" selectedKey = {student.Choice} options = {choices} onChange = {(e: any, selectedItem: any) => ...} />);

    els.push(<TextField label='Name' required value = {student.Name} onChange = {(e: any, value: any) => ....} validateOnLoad = {false} 
        onGetErrorMessage = {(value: string) => validate('Name', value, els)} />);
    els.push(<TextField key='Age' label="Age" required value = {student.Age} onChange = {(e: any, value: any) => ..} validateOnLoad = {false}
        onGetErrorMessage = {(value: string) => validate('Age', value, els)} />);

We have 3 elements, which are shown, now on choice change, I need to clear the textfields, which I do as follows:

useEffect(() => {
        // I modify the state here, and set Age and Name of the student object to ''
        // which triggers then onGetErrorMessage

    }, [student.Choice]);

What is the best way to reset values of the textfields, without triggering validate, but this still has to work when user manually clears textfield (making it empty)

Any idea? I would appreciate .... been stuck with it for some time...


Solution

  • Since you explained the behavior of validateOnLoad you can supply keys to your textfields:

    <TextField
      label="Name"
      key={uniqueKey}
      required
      value={student.Name}
      onChange={(e: any, value: any) => {
        /* ... */
      }}
      validateOnLoad={false}
      onGetErrorMessage={(value: string) => validate("Name", value, els)}
    />;
    

    Now, when you clear Age and Name inside useEffect, you can also regenerate keys of each text field. The key should be a unique value like UUID. This will make react unmount the previous instance of each Textfield and mount it again - which will give you same behavior you had when you initially created each text field.

    The keys should be generated initially once, and also make sure you regenerate those keys in useEffect when you want to clear those text fields, and not inside render on each rerender (see example below).

    Example:

    import React from 'react';
    import './style.css';
    
    // Using this function for this example, not sure if this is the safest way to generate uuidv4
    function uuidv4() {
      return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
        (
          c ^
          (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
        ).toString(16)
      );
    }
    
    export default function App() {
      let [a, setA] = React.useState(uuidv4());
      let [b, setB] = React.useState(uuidv4());
      let [test, setTest] = React.useState(0);
    
      React.useEffect(() => {
        setA(uuidv4());
        setB(uuidv4());
      }, [test]);
      return (
        <div>
          <input key={a}></input>
          <input key={b}></input>
          <button
            onClick={() => {
              setTest(test + 1);
            }}
          >
            click
          </button>
        </div>
      );
    }