Perform validation before every render

Viewed 495

I'm working on this component and I want to validate its fields before every render. If they are not valid I want to disable a button in the parent.

Here is what I've got thus far:

export default function Input(props) {

  const [inputs] = useState(props.inputs);

  const didChangeRef = useRef([]);

  useEffect(() => {
    if (!_.isEqual(didMountRef.current, props.inputs)) {
      validateInput(input);
      didChangeRef.current = props.inputs;
    }
  });

  const validateInput = input => {
     const errors = useValidation(input);
     if(Object.keys(errors).length !== 0) {
       props.setIsValid(false);
     }
  }

 return (
  <input
   onChange={e=> props.setProperty(e)}>
  </input>
  <input
   onChange={e=> props.setProperty(e)}>
  </input>
 )
}

If an input is changed, it sets a property in the parent and this component is re-rendered. Inputs is an array of objects and I wish to validate it's contents on each render (or componentDidMount). I either manage to get it to loop infinitely or run the validation only once.

I appreciate your help.

P.S.:

I tried another approach as well, but it still ends up looping infinately:

export default function Input(props) {

  const didMountRef = useRef(true);

  useLayoutEffect(() => {
    if (didMountRef.current) {
      didMountRef.current = false;
      return;
    }
    validate(input);
  });

  const validate = input => {
    // validation...
  }

}

Here is the parent component:

class CreateShoppingItem extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      storage: {},
      isValid: true,
    };
  }

  setIsValid = (isValid) => {
    this.setState({ isValid });
  };

  render() {
    return (
      <div>
        <Input setIsValid={this.setIsValid} inputs={this.storage.inputs} />
        <Button disable={!isValid}></Button>
      </div>
    );
  }
}
0 Answers
Related