Hone logo
Hone
Problems

Building a Labeled Input Component in React with TypeScript

This challenge focuses on creating a reusable React component that renders an input field alongside a descriptive label. This is a fundamental building block for any form and demonstrates understanding of component composition, props, and TypeScript typing. Successfully completing this challenge will solidify your ability to create modular and type-safe React components.

Problem Description

You are tasked with creating a LabeledInput component in React using TypeScript. This component should accept a label text, an input type (e.g., "text", "number", "email"), and a value as props. The component should render an HTML <label> element associated with an HTML <input> element. The label's for attribute should correspond to the input's id attribute, ensuring proper accessibility. The input's value attribute should be dynamically set based on the value prop. The component should also accept an onChange prop, which is a function that will be called when the input's value changes.

Key Requirements:

  • Label and Input Association: The label must be correctly associated with the input using the for and id attributes.
  • Dynamic Value: The input's value attribute must be controlled by the value prop.
  • Change Handling: The component must correctly call the onChange prop when the input value changes.
  • Input Type: The input's type attribute must be set based on the type prop.
  • TypeScript Typing: The component must be written in TypeScript with appropriate type definitions for props.

Expected Behavior:

When the component is rendered, it should display a label above an input field. The input field should initially have the value specified by the value prop. As the user types into the input field, the onChange prop function should be called with the new input value.

Edge Cases to Consider:

  • Empty label text: Handle the case where the label prop is an empty string gracefully (e.g., by not rendering the label).
  • Invalid input type: While not strictly required, consider how you might handle an invalid type prop (e.g., by logging a warning or using a default type).

Examples

Example 1:

Input: <LabeledInput label="Name" type="text" value="John Doe" onChange={(e) => console.log(e.target.value)} />
Output:
<label for="name-input">Name</label>
<input type="text" id="name-input" value="John Doe" onChange={(e) => console.log(e.target.value)}/>
Explanation: A label "Name" is associated with a text input field initialized with the value "John Doe".  The onChange handler logs the input value to the console.

Example 2:

Input: <LabeledInput label="Age" type="number" value="25" onChange={(e) => console.log(e.target.value)} />
Output:
<label for="age-input">Age</label>
<input type="number" id="age-input" value="25" onChange={(e) => console.log(e.target.value)}/>
Explanation: A label "Age" is associated with a number input field initialized with the value "25". The onChange handler logs the input value to the console.

Example 3: (Edge Case)

Input: <LabeledInput label="" type="email" value="test@example.com" onChange={(e) => console.log(e.target.value)} />
Output:
<input type="email" id="email-input" value="test@example.com" onChange={(e) => console.log(e.target.value)}/>
Explanation: Because the label is empty, the label element is not rendered. The email input field is initialized with the value "test@example.com".

Constraints

  • The component must be written in functional component style using React Hooks (if needed).
  • The component must be written in TypeScript.
  • The id attribute for the input field should be dynamically generated based on the label prop (e.g., label.toLowerCase().replace(/ /g, '-') + '-input').
  • The component should be reusable and accept different input types and values.

Notes

  • Consider using a unique identifier for the input field's id to avoid conflicts if you use multiple LabeledInput components on the same page.
  • Think about how you might handle optional props like placeholder or required. While not required for this challenge, it's good practice to consider extensibility.
  • Focus on creating a clean, readable, and well-typed component. Accessibility is key, so ensure the label and input are properly associated.
Loading editor...
typescript