Component & Function Generation with AI | Learn2Vibe

# Component and Function Generation: Building Real Features with AI You've probably used AI to explain code or debug a tricky issue. But the real power of vibe coding emerges when you start generating entire components and functions from scratch. This isn't about blindly accepting AI output—it's about treating AI as a collaborative partner that accelerates your development workflow while you maintain control and quality. ## Understanding Generation vs. Completion Before diving in, let's clarify what we mean by "generation." Code *completion* suggests the next few lines based on context. Code *generation* creates entire functional units—components, functions, classes—from a description of what you need. When you ask an AI to "create a user authentication function," you're not getting autocomplete. You're getting a complete implementation that you'll need to review, test, and integrate. This distinction matters because it changes your role from writer to editor-in-chief. ## The Component Generation Workflow Effective component generation follows a consistent pattern: 1. **Specify requirements clearly** 2. **Generate initial implementation** 3. **Review for correctness and patterns** 4. **Iterate with refinements** 5. **Test and validate** 6. **Document and integrate** Let's walk through this with a real example. ## Practical Example: Building a Data Table Component Suppose you need a reusable data table component for a React application. Here's how to approach it: ### Step 1: Craft a Specific Prompt Vague prompts get vague results. Compare these: ❌ **Vague:** "Make me a table component" ✅ **Specific:** "Create a React TypeScript component called DataTable that accepts an array of objects and displays them in a sortable table. Include props for data, columns (with header and accessor), and an onRowClick handler. Use Tailwind CSS for styling." The specific prompt includes: - Technology stack (React, TypeScript, Tailwind) - Component name - Core functionality (sortable) - Required props with types - Expected behavior ### Step 2: Review the Generated Code Here's what the AI might generate: ```typescript import React, { useState } from 'react'; interface Column { header: string; accessor: keyof T; sortable?: boolean; } interface DataTableProps { data: T[]; columns: Column[]; onRowClick?: (row: T) => void; } export function DataTable({ data, columns, onRowClick }: DataTableProps) { const [sortConfig, setSortConfig] = useState<{ key: keyof T; direction: 'asc' | 'desc'; } | null>(null); const sortedData = React.useMemo(() => { if (!sortConfig) return data; return [...data].sort((a, b) => { const aVal = a[sortConfig.key]; const bVal = b[sortConfig.key]; if (aVal < bVal) return sortConfig.direction === 'asc' ? -1 : 1; if (aVal > bVal) return sortConfig.direction === 'asc' ? 1 : -1; return 0; }); }, [data, sortConfig]); const handleSort = (key: keyof T) => { setSortConfig((current) => { if (!current || current.key !== key) { return { key, direction: 'asc' }; } if (current.direction === 'asc') { return { key, direction: 'desc' }; } return null; }); }; return (
{columns.map((column) => ( ))} {sortedData.map((row, idx) => ( onRowClick?.(row)} className={onRowClick ? 'cursor-pointer hover:bg-gray-50' : ''} > {columns.map((column) => ( ))} ))}
column.sortable !== false && handleSort(column.accessor)} className={`px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider ${ column.sortable !== false ? 'cursor-pointer hover:bg-gray-100' : '' }`} > {column.header} {sortConfig?.key === column.accessor && ( {sortConfig.direction === 'asc' ? '↑' : '↓'} )}
{String(row[column.accessor])}
); } ``` ### Step 3: Critical Review Checklist Now comes the crucial part—reviewing what was generated. Apply these checks: **Type Safety:** - ✅ Generic type `` allows reusability - ✅ Proper TypeScript interfaces - ⚠️ Missing unique key generation (uses array index) **Performance:** - ✅ Uses `useMemo` for sorted data - ✅ Proper dependency array - ⚠️ No virtualization for large datasets **Accessibility:** - ⚠️ Missing ARIA labels - ⚠️ No keyboard navigation - ⚠️ Sort button isn't announced to screen readers **Edge Cases:** - ⚠️ No empty state handling - ⚠️ No loading state - ⚠️ String conversion might fail for complex objects This is where your expertise matters. The AI gave you a solid foundation, but identified several improvements needed for production use. For more on this review process, see [review-refactor](/lessons/review-refactor). ### Step 4: Iterate with Targeted Prompts Don't regenerate everything. Make targeted improvements: ``` "Add proper accessibility attributes for the sortable headers, including aria-sort and keyboard navigation support. Also add an empty state when data array is empty." ``` This focused approach prevents losing good work while addressing specific gaps. ## Function Generation Best Practices When generating standalone functions, the principles remain similar but with additional considerations. ### Example: Generating a Validation Function **Prompt:** ``` Create a TypeScript function that validates email addresses according to RFC 5322. Include: - Full type definitions - Comprehensive error messages - JSDoc comments - Unit test examples ``` **Generated Output:** ```typescript /** * Validates an email address according to RFC 5322 standards * @param email - The email address to validate * @returns Object with isValid boolean and optional error message */ export function validateEmail(email: string): { isValid: boolean; error?: string; } { if (!email || typeof email !== 'string') { return { isValid: false, error: 'Email must be a non-empty string', }; } if (email.length > 254) { return { isValid: false, error: 'Email address exceeds maximum length of 254 characters', }; } const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { return { isValid: false, error: 'Email format is invalid', }; } const [localPart, domain] = email.split('@'); if (localPart.length > 64) { return { isValid: false, error: 'Local part of email exceeds 64 characters', }; } return { isValid: true }; } // Example usage and tests const testCases = [ { email: 'user@example.com', expected: true }, { email: 'invalid.email', expected: false }, { email: 'a'.repeat(65) + '@example.com', expected: false }, ]; ``` **Review considerations:** - The regex is simplified (RFC 5322 is complex) - Missing internationalized domain support - Good error messages for debugging - Documentation included You'd then decide: is this sufficient for your use case, or do you need the full RFC 5322 complexity? This is a judgment call AI can't make for you. ## Managing Complexity: Breaking Down Large Generations For complex features, generate in layers rather than all at once. Consider a user dashboard: **Phase 1:** Generate the component shell ``` "Create a React dashboard component structure with sections for user stats, recent activity, and quick actions. Use placeholder content for now." ``` **Phase 2:** Generate individual sections ``` "Now create the UserStats component that displays user metrics in a card grid. Props should include stats array with label, value, and change percentage." ``` **Phase 3:** Add interactivity ``` "Add filtering and date range selection to the recent activity section. Use React hooks for state management." ``` This incremental approach: - Keeps each generation manageable - Allows review between steps - Makes debugging easier - Prevents overwhelming context For strategies on managing this complexity at scale, check out [scaling-vibe-coding](/lessons/scaling-vibe-coding). ## Common Pitfalls and How to Avoid Them ### Pitfall 1: Over-Engineering AI often generates overly complex solutions. If you ask for "a function to sum numbers," you might get: ```typescript // Over-engineered class NumberSummer { private numbers: number[]; constructor(numbers: number[]) { this.numbers = numbers; } public sum(): number { return this.numbers.reduce((acc, curr) => acc + curr, 0); } } ``` When this works fine: ```typescript // Appropriate const sum = (numbers: number[]) => numbers.reduce((a, b) => a + b, 0); ``` **Solution:** Specify "simple" or "minimal" in your prompt when appropriate. ### Pitfall 2: Inconsistent Patterns AI doesn't know your codebase conventions. It might generate: - Different naming conventions - Inconsistent error handling - Various state management approaches **Solution:** Include your project's patterns in the prompt: ``` "Follow our project conventions: use camelCase for variables, PascalCase for components, handle errors with our useError hook, and use Zustand for state management." ``` ### Pitfall 3: Missing Security Considerations AI-generated code may have security vulnerabilities. Always review for: - Input validation - XSS prevention - SQL injection (if applicable) - Authentication checks - Data exposure For deep dives on this topic, see [security-considerations](/lessons/security-considerations). ## Integration Strategies Generated code rarely works perfectly with existing systems. Here's how to integrate smoothly: ### 1. Adapt to Your Architecture If your app uses a specific state management library, API client, or styling system, specify it upfront or adapt the generated code: ```typescript // Generated with generic fetch const data = await fetch('/api/users').then(r => r.json()); // Adapted to your API client const data = await apiClient.get('/users'); ``` ### 2. Match Your Testing Strategy Generate tests alongside components: ``` "Also create Jest tests for this component using React Testing Library, following our pattern of user-centric queries and avoiding implementation details." ``` Learn more about comprehensive testing approaches in [testing-strategies](/lessons/testing-strategies). ### 3. Maintain Documentation Always ask for documentation: ``` "Include JSDoc comments, a usage example, and update the README with this new component." ``` Or leverage [doc-generation](/lessons/doc-generation) techniques to create documentation separately. ## Quality Control Checklist Before considering AI-generated code complete: - [ ] Code follows project conventions - [ ] TypeScript types are accurate (no `any`) - [ ] Error handling is comprehensive - [ ] Edge cases are covered - [ ] Performance is acceptable - [ ] Security vulnerabilities addressed - [ ] Accessibility requirements met - [ ] Tests are included and passing - [ ] Documentation is clear - [ ] No obvious bugs or logic errors This checklist prevents the common trap of shipping generated code without proper validation. For more on maintaining quality, see [quality-control](/lessons/quality-control). ## When to Generate vs. When to Write Not everything should be AI-generated. Use generation for: ✅ **Good candidates:** - Boilerplate components (forms, tables, modals) - Standard CRUD operations - Common utility functions - Test scaffolding - Type definitions from schemas ❌ **Poor candidates:** - Core business logic with complex rules - Security-critical functions - Performance-critical algorithms - Code requiring deep domain knowledge - Innovative or novel solutions For more guidance, check out [when-not-to-use-ai](/lessons/when-not-to-use-ai). ## Advanced Technique: Iterative Refinement Treat AI generation as a conversation, not a one-shot command: 1. **Initial generation:** Get the basic structure 2. **Add constraints:** "Make this component responsive" 3. **Improve patterns:** "Use composition instead of prop drilling" 4. **Optimize:** "Reduce re-renders with React.memo" 5. **Enhance:** "Add loading and error states" Each iteration builds on the previous, allowing you to shape the code gradually while maintaining control. ## Tracking and Learning from Generated Code Keep a log of what works and what doesn't: ```markdown ## Generation Log ### 2024-01-15: Modal Component - **Prompt:** "Create accessible modal with focus trap" - **Result:** Good structure, missing escape key handler - **Lesson:** Always specify keyboard interactions explicitly ### 2024-01-16: API Hook - **Prompt:** "Create React hook for fetching user data" - **Result:** Missing error retry logic - **Lesson:** Include error handling requirements in prompt ``` This practice improves your prompting skills over time and builds a knowledge base for your team. Consider integrating this with [version-control-ai](/lessons/version-control-ai) practices. ## Collaborative Generation When working with teams, establish generation standards: 1. **Prompt templates** for common components 2. **Review requirements** before committing generated code 3. **Shared learning** about what prompts work best 4. **Code ownership** clarity (who validates AI output?) Explore more team practices in [team-workflows](/lessons/team-workflows). ## Measuring Success Track these metrics to evaluate your component generation effectiveness: - **Time to first working version** (should decrease) - **Iterations needed** (should decrease with better prompts) - **Bugs in generated code** (should decrease with better reviews) - **Code reuse** (generated components used elsewhere) ## Your Action Plan Start applying component and function generation today: 1. **This week:** Generate one utility function you need, review it thoroughly, and document what you learned 2. **Next week:** Generate a simple component, add tests, and integrate it into your project 3. **This month:** Create a prompt library for your most common generation tasks 4. **Ongoing:** Build your review checklist based on issues you discover Remember: AI generates code, but you're responsible for what ships. The goal isn't to eliminate thinking—it's to eliminate tedious work so you can focus on architecture, logic, and user experience. Master component generation, and you'll find yourself building features faster without sacrificing quality. The key is treating AI as a tool that enhances your expertise, not replaces it.