# From React to Aurelia

**Coming from React?** You'll love Aurelia's approach to component development. Get the productivity of React with better performance, cleaner templates, and no virtual DOM overhead.

## Why React Developers Choose Aurelia

### **🚀 Performance That Actually Matters**

```typescript
// React: Virtual DOM reconciliation overhead
function UserList({ users, onUserClick }) {
  return (
    <div>
      {users.filter(u => u.isActive).map(user => (
        <UserCard key={user.id} user={user} onClick={onUserClick} />
      ))}
    </div>
  );
}

// Aurelia: Direct DOM updates, no virtual overhead
export class UserList {
  @bindable users: User[];
  @bindable onUserClick: (user: User) => void;
}
```

```html
<!-- Aurelia template: Clean HTML, faster rendering -->
<div>
  <user-card repeat.for="user of users.filter(u => u.isActive)" 
             user.bind="user" 
             on-click.bind="() => onUserClick(user)">
  </user-card>
</div>
```

**Result:** 30-50% faster rendering with smaller bundle sizes.

### **✨ Cleaner Component Code**

```typescript
// React: Hooks complexity and re-render management
function SearchComponent() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);

  const debouncedSearch = useCallback(
    debounce(async (searchTerm) => {
      setLoading(true);
      try {
        const data = await searchAPI(searchTerm);
        setResults(data);
      } finally {
        setLoading(false);
      }
    }, 300),
    []
  );

  useEffect(() => {
    if (query.length > 2) {
      debouncedSearch(query);
    } else {
      setResults([]);
    }
  }, [query, debouncedSearch]);

  return (
    <div>
      <input 
        value={query} 
        onChange={(e) => setQuery(e.target.value)}
        placeholder="Search..."
      />
      {loading && <div>Loading...</div>}
      {results.map(result => <Result key={result.id} data={result} />)}
    </div>
  );
}

// Aurelia: Simple, intuitive code
export class SearchComponent {
  query = '';
  results: SearchResult[] = [];
  loading = false;

  @watch('query')
  async queryChanged(newQuery: string) {
    if (newQuery.length > 2) {
      this.loading = true;
      try {
        this.results = await searchAPI(newQuery);
      } finally {
        this.loading = false;
      }
    } else {
      this.results = [];
    }
  }
}
```

```html
<div>
  <input value.bind="query & debounce:300" placeholder="Search...">
  <div if.bind="loading">Loading...</div>
  <result repeat.for="result of results" data.bind="result"></result>
</div>
```

**No hooks complexity. No re-render cycles. Just clean, maintainable code.**

### **🎯 TypeScript-First Development**

```typescript
// React: Complex prop typing
interface UserCardProps {
  user: User;
  onEdit?: (user: User) => void;
  onDelete?: (user: User) => void;
  className?: string;
  children?: React.ReactNode;
}

const UserCard: React.FC<UserCardProps> = ({ 
  user, onEdit, onDelete, className, children 
}) => {
  // Component logic
};

// Aurelia: Built-in TypeScript support
export class UserCard {
  @bindable user: User;
  @bindable onEdit?: (user: User) => void;
  @bindable onDelete?: (user: User) => void;
  
  // Automatic type checking, no prop interfaces needed
}
```

### **🔥 Better Developer Experience**

| Feature             | React                                   | Aurelia                               |
| ------------------- | --------------------------------------- | ------------------------------------- |
| **Component State** | useState, useReducer                    | Simple class properties               |
| **Side Effects**    | useEffect with dependencies             | @watch decorator or lifecycle hooks   |
| **Performance**     | memo, useMemo, useCallback              | Automatic optimization                |
| **Styling**         | CSS-in-JS or external files             | Automatic CSS loading + Shadow DOM    |
| **Forms**           | Controlled components + validation libs | Two-way binding + built-in validation |

## Your React Knowledge Transfers

### **JSX → Aurelia Templates**

```jsx
// React JSX
<div className={`card ${isActive ? 'active' : ''}`}>
  <h2>{user.name}</h2>
  <button onClick={() => handleEdit(user)}>Edit</button>
  {showDetails && (
    <div>
      <p>{user.bio}</p>
      {user.posts.map(post => (
        <PostCard key={post.id} post={post} />
      ))}
    </div>
  )}
</div>

// Aurelia HTML (cleaner, more intuitive)
<div class="card" active.class="isActive">
  <h2>${user.name}</h2>
  <button click.trigger="handleEdit(user)">Edit</button>
  <div if.bind="showDetails">
    <p>${user.bio}</p>
    <post-card repeat.for="post of user.posts" post.bind="post"></post-card>
  </div>
</div>
```

### **Props → Bindable Properties**

```tsx
// React
interface Props {
  data: any[];
  onItemClick: (item: any) => void;
  loading?: boolean;
}

const MyComponent: React.FC<Props> = ({ data, onItemClick, loading = false }) => {
  // Component logic
};

// Aurelia
export class MyComponent {
  @bindable data: any[];
  @bindable onItemClick: (item: any) => void;
  @bindable loading = false;
  
  // That's it - cleaner and more intuitive
}
```

### **State Management**

```typescript
// React: Context + useReducer or external library
const UserContext = createContext();

function UserProvider({ children }) {
  const [state, dispatch] = useReducer(userReducer, initialState);
  return (
    <UserContext.Provider value={{ state, dispatch }}>
      {children}
    </UserContext.Provider>
  );
}

// Aurelia: Built-in dependency injection
@singleton()
export class UserService {
  private users: User[] = [];
  
  addUser(user: User) {
    this.users.push(user);
  }
  
  getUsers() {
    return this.users;
  }
}

// Use anywhere with simple injection
export class UserList {
  private userService = resolve(UserService);
  
  get users() {
    return this.userService.getUsers();
  }
}
```

## Quick Migration Path

### **1. Start with Familiar Concepts (5 minutes)**

```bash
npx makes aurelia my-aurelia-app
cd my-aurelia-app
npm run dev
```

### **2. Convert a React Component (10 minutes)**

Create your first Aurelia component using familiar React patterns:

```typescript
// React component you're used to
const TodoList = ({ todos, onToggle, onDelete }) => (
  <ul>
    {todos.map(todo => (
      <li key={todo.id}>
        <input 
          type="checkbox" 
          checked={todo.completed}
          onChange={() => onToggle(todo.id)}
        />
        <span>{todo.text}</span>
        <button onClick={() => onDelete(todo.id)}>Delete</button>
      </li>
    ))}
  </ul>
);

// Equivalent Aurelia component
export class TodoList {
  @bindable todos: Todo[];
  @bindable onToggle: (id: number) => void;
  @bindable onDelete: (id: number) => void;
}
```

```html
<!-- todo-list.html -->
<ul>
  <li repeat.for="todo of todos">
    <input type="checkbox" 
           checked.bind="todo.completed"
           change.trigger="onToggle(todo.id)">
    <span>${todo.text}</span>
    <button click.trigger="onDelete(todo.id)">Delete</button>
  </li>
</ul>
```

### **3. Experience the Differences (5 minutes)**

* **No build step complexity** - just works with any bundler
* **No prop drilling** - dependency injection handles state
* **No re-render debugging** - direct DOM updates
* **No hooks confusion** - simple class properties and methods

## What You'll Gain

### **📈 Performance Benefits**

* **Faster initial load** - no virtual DOM library overhead
* **Faster updates** - direct DOM manipulation
* **Smaller bundles** - efficient code splitting
* **Better mobile performance** - less JavaScript execution

### **🧹 Cleaner Codebase**

* **Less boilerplate** - no prop interfaces, no memo wrapping
* **Intuitive templates** - HTML that looks like HTML
* **Simpler state management** - class properties instead of hooks
* **Better separation of concerns** - HTML, CSS, and TypeScript in separate files

### **🚀 Better Developer Experience**

* **Stronger TypeScript integration** - built from the ground up for TypeScript
* **No re-render optimization needed** - automatically efficient
* **Powerful CLI tools** - scaffolding and build tools that just work
* **Excellent debugging** - inspect actual DOM, not virtual representations

## Ready to Make the Switch?

```bash
# Try Aurelia now
npx makes aurelia my-first-aurelia-app
cd my-first-aurelia-app
npm run dev
```

**Next Steps:**

1. [**Complete Getting Started Guide**](https://docs.aurelia.io/getting-started/complete-guide) - Build your first app in 15 minutes
2. [**Component Guide**](https://docs.aurelia.io/components/components) - Master Aurelia's component model
3. [**Templates Deep Dive**](https://docs.aurelia.io/templates/overview) - Learn the templating system
4. [**Migration Examples**](https://docs.aurelia.io/migrating-to-aurelia-2/migrating-to-aurelia-2) - See more migration patterns

**Questions?** Join our [Discord community](https://discord.gg/RBtyM6u) where developers discuss their experiences with different frameworks.

**Ready to experience the difference?** [Start building with Aurelia now](https://docs.aurelia.io/getting-started/complete-guide).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.aurelia.io/coming-from-another-framework/from-react.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
