# React Guidelines
## Core React Principles
Twenty follows modern React best practices with a focus on functional components and clean, maintainable code. This document outlines our React conventions and best practices.
## Component Structure
### Functional Components Only
- Use functional components exclusively
- No class components allowed
```typescript
// ✅ Correct
export const UserProfile = ({ user }: UserProfileProps) => {
return (
{user.name}
);
};
// ❌ Incorrect
export class UserProfile extends React.Component {
render() {
return (
{this.props.user.name}
);
}
}
```
### Named Exports
- Use named exports exclusively
- No default exports
```typescript
// ✅ Correct
export const Button = ({ label }: ButtonProps) => {
return {label} ;
};
// ❌ Incorrect
export default function Button({ label }: ButtonProps) {
return {label} ;
}
```
## State and Effects
### Event Handlers Over useEffect
- Prefer event handlers for state updates
- Avoid useEffect for state synchronization
```typescript
// ✅ Correct
const UserForm = () => {
const handleSubmit = async (data: FormData) => {
await updateUser(data);
refreshUserList();
};
return ;
};
// ❌ Incorrect
const UserForm = () => {
useEffect(() => {
if (formData) {
updateUser(formData);
}
}, [formData]);
return ;
};
```
## Component Design
### Small, Focused Components
- Keep components small and single-purpose
- Extract reusable logic into custom hooks
```typescript
// ✅ Correct
const UserCard = ({ user }: UserCardProps) => {
return (
);
};
// ❌ Incorrect
const UserCard = ({ user }: UserCardProps) => {
return (
{/* Too much logic in one component */}
{user.name}
{user.email}
handleEdit(user)}>Edit
handleDelete(user)}>Delete
{/* More complex logic... */}
);
};
```
## Props
### Prop Naming
- Use clear, descriptive prop names
- Follow React conventions (onClick, isActive, etc.)
```typescript
// ✅ Correct
type ButtonProps = {
onClick: () => void;
isDisabled?: boolean;
isLoading?: boolean;
};
// ❌ Incorrect
type ButtonProps = {
clickHandler: () => void;
disabled?: boolean;
loading?: boolean;
};
```
### Prop Destructuring
- Destructure props with proper typing
- Use TypeScript for prop types
```typescript
// ✅ Correct
const Button = ({ onClick, isDisabled, children }: ButtonProps) => {
return (
{children}
);
};
// ❌ Incorrect
const Button = (props: ButtonProps) => {
return (
{props.children}
);
};
```
## Performance Optimization
### Memoization
- Use memo for expensive computations
- Avoid premature optimization
```typescript
// ✅ Correct - Complex computation
const MemoizedChart = memo(({ data }: ChartProps) => {
// Complex rendering logic
return ;
});
// ❌ Incorrect - Unnecessary memoization
const MemoizedText = memo(({ text }: { text: string }) => {
return {text} ;
});
```
### Event Handlers
- Use callback refs for DOM manipulation
- Memoize callbacks when needed
```typescript
// ✅ Correct
const UserList = () => {
const handleScroll = useCallback((event: UIEvent) => {
// Complex scroll handling
}, []);
return {/* content */}
;
};
```
## Error Handling
### Error Boundaries
- Use error boundaries for component error handling
- Provide meaningful fallback UIs
```typescript
// ✅ Correct
const ErrorFallback = ({ error }: { error: Error }) => (
Something went wrong
{error.message}
);
const SafeComponent = () => (
);
```
### Loading States
- Handle loading states gracefully
- Provide meaningful loading indicators
```typescript
// ✅ Correct
const UserProfile = () => {
const { data: user, isLoading, error } = useUser();
if (isLoading) return ;
if (error) return ;
if (!user) return ;
return ;
};
```