Sortable List Component in React with TypeScript
This challenge asks you to build a reusable React component that displays a list of items and allows the user to sort them via drag-and-drop. Creating sortable lists is a common UI requirement in applications like task management tools, dashboards, and content management systems, and this exercise will test your understanding of React state management, event handling, and potentially a drag-and-drop library.
Problem Description
You need to implement a SortableList component in React using TypeScript. This component should:
- Accept a prop:
items: An array of objects. Each object in the array should have a uniqueidproperty (string or number) and alabelproperty (string). - Display the items: Render each item in the
itemsarray as a list item (<li>). Thelabelproperty should be displayed within each list item. - Enable Drag-and-Drop Sorting: Allow users to drag and drop list items to reorder them. You can use a library like
react-beautiful-dndor implement a basic drag-and-drop mechanism yourself (though using a library is highly recommended for a robust solution). - Update State: When the user reorders the items, the component should update its internal state to reflect the new order.
- Re-render: After the state is updated, the component should re-render to display the items in the new sorted order.
Key Requirements:
- The component must be functional and written in TypeScript.
- The component should be reusable and accept the
itemsprop. - The drag-and-drop functionality should be intuitive and responsive.
- The component should handle edge cases gracefully (e.g., empty list).
Expected Behavior:
- Initially, the list items should be displayed in the order they appear in the
itemsprop. - When a user drags a list item, the other items should visually indicate that they can be dropped.
- When a user drops a list item, the list items should reorder themselves to reflect the new position.
- The component should re-render to display the updated list order.
Edge Cases to Consider:
- Empty list: The component should render an empty state (e.g., a message indicating that there are no items).
- Duplicate IDs: While not explicitly required to handle, consider how your solution would behave if the input
itemsarray contained duplicateidvalues. (Ideally, the library you choose would handle this, or you would add validation).
Examples
Example 1:
Input: items = [{ id: '1', label: 'Item A' }, { id: '2', label: 'Item B' }, { id: '3', label: 'Item C' }]
Output: A list displaying "Item A", "Item B", and "Item C" in that order. Dragging "Item B" above "Item A" would reorder the list to display "Item B", "Item A", "Item C".
Explanation: The component renders the initial list and updates the order based on drag-and-drop interactions.
Example 2:
Input: items = []
Output: A message indicating that the list is empty (e.g., "No items to display").
Explanation: The component handles the edge case of an empty list gracefully.
Example 3:
Input: items = [{ id: '1', label: 'Item A' }, { id: '2', label: 'Item B' }, { id: '3', label: 'Item C' }, { id: '4', label: 'Item D' }]
Output: A list displaying "Item A", "Item B", "Item C", and "Item D". Dragging "Item D" to the top would reorder the list to display "Item D", "Item A", "Item B", "Item C".
Explanation: The component handles lists of varying lengths and reorders them correctly.
Constraints
- Component Structure: The component must be a functional React component.
- TypeScript: The code must be written in TypeScript.
- Library Usage: While you can implement a basic drag-and-drop mechanism, using a library like
react-beautiful-dndis strongly recommended for a more robust and performant solution. If using a library, ensure it's properly installed and configured. - Performance: The component should be performant, even with a large number of items (e.g., 100+). Consider using techniques like memoization or virtualization if necessary (though not strictly required for this challenge).
- Input Type: The
itemsprop must be an array of objects, where each object has anid(string or number) and alabel(string) property.
Notes
- Consider using a state management solution (e.g.,
useState) to manage the list order. - Think about how to efficiently update the state when the list is reordered.
- Pay attention to accessibility when implementing the drag-and-drop functionality. Ensure that users can interact with the list using a keyboard.
- Focus on creating a clean, well-structured, and reusable component.
- If using
react-beautiful-dnd, refer to its documentation for guidance on implementing drag-and-drop functionality: https://github.com/atlassian/react-beautiful-dnd