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
labelandid. - Maintain the input's value using the
valueprop. - Call the
onChangeprop function whenever the input value changes. - Validate the input value against the
validationRegex. - Display the
errorMessagebelow 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
validationRegexis 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
useStatehook to manage the input value. - The component must handle the
onChangeevent correctly. - The component must validate the input against the provided
validationRegex. - The component must display the
errorMessageconditionally. - 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
useEffecthook 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
validationRegexis not provided. Treating it as no validation is a reasonable approach. - The
onChangeprop is crucial for maintaining the controlled nature of the component. Ensure it's called with the correct value.