Hone logo
Hone
Problems

Controlled Input Component with Validation in React

This challenge asks you to build a reusable React component that represents a controlled input field with built-in validation. Controlled components are fundamental to React development, allowing you to manage and control the input's value and behavior through state. This component will demonstrate how to handle user input, validate it, and update the component's state accordingly.

Problem Description

You need to create a ControlledInput component in React using TypeScript. This component should accept the following props:

  • label: (string) The label for the input field.
  • value: (string) The initial value of the input field. This is the controlled value.
  • onChange: (function) A function to be called when the input value changes. This function will receive the new value as an argument.
  • validationRegex: (RegExp) A regular expression used to validate the input.
  • errorMessage: (string) The error message to display if the input is invalid.
  • id: (string) The ID of the input element.

The component should:

  • Render an input field with the provided label and id.
  • Maintain the input's value using the value prop.
  • Call the onChange prop function whenever the input value changes.
  • Validate the input value against the validationRegex.
  • Display the errorMessage below the input field if the input is invalid. The error message should only be displayed when the input is not valid.
  • The component should handle the case where validationRegex is null or undefined (treat as no validation).

Expected Behavior:

The component should update its state (internally) to reflect the current input value. The onChange prop should be called with the new value whenever the user types in the input field. The validation should occur after the onChange prop is called, and the error message should be displayed conditionally.

Examples

Example 1:

Input:
<ControlledInput
  label="Email"
  value=""
  onChange={() => {}}
  validationRegex=/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/
  errorMessage="Please enter a valid email address"
  id="email"
/>
Output:
<input type="text" id="email" />

Explanation: A simple email input field with no initial value and a validation regex. No error message is displayed initially.

Example 2:

Input:
<ControlledInput
  label="Username"
  value="invalid-username"
  onChange={() => {}}
  validationRegex=/^[a-zA-Z0-9_]{3,16}$/
  errorMessage="Username must be between 3 and 16 characters and contain only letters, numbers, and underscores."
  id="username"
/>
Output:
<input type="text" id="username" value="invalid-username" />
<p style={{ color: 'red' }}>Username must be between 3 and 16 characters and contain only letters, numbers, and underscores.</p>

Explanation: The input field is pre-populated with an invalid username. The error message is displayed because the value doesn't match the regex.

Example 3: (Edge Case - No Validation)

Input:
<ControlledInput
  label="Free Text"
  value="Some text"
  onChange={() => {}}
  validationRegex={null}
  errorMessage="This is an error message"
  id="freeText"
/>
Output:
<input type="text" id="freeText" value="Some text" />

Explanation: The validationRegex is null. No validation occurs, and the error message is not displayed.

Constraints

  • The component must be written in TypeScript.
  • The component must be a functional component.
  • The component must use React's useState hook to manage the input value.
  • The component must handle the onChange event correctly.
  • The component must validate the input against the provided validationRegex.
  • The component must display the errorMessage conditionally.
  • The component should not perform validation on initial render if the value prop is provided. Validation should only occur on onChange.

Notes

  • Consider using a useEffect hook to perform side effects if needed (though it's not strictly required for this problem).
  • Focus on creating a clean, reusable, and well-documented component.
  • The styling of the input field and error message is not a primary concern; focus on the functionality. A simple inline style for the error message is acceptable.
  • Think about how to handle the case where the validationRegex is not provided. Treating it as no validation is a reasonable approach.
  • The onChange prop is crucial for maintaining the controlled nature of the component. Ensure it's called with the correct value.
Loading editor...
typescript