react-spa-template/docs/flux-vs-mvvm.md
2025-04-19 19:24:27 +02:00

65 lines
2.7 KiB
Markdown

# Flux vs. MVVM Architecture
## Decision Matrix: Flux vs. MVVM
| Criterion | Plain Effector (Flux) | MVVM Layer on Top |
|-----------|----------------------|-------------------|
| Boilerplate | Low | Higher |
| React Ecosystem Fit | Native | Non-idiomatic |
| Two-way Binding Risk | None | Possible |
| Testability | High (domain files are pure) | High but more layers |
| Refactor Complexity | Lower | Higher |
## Why We Chose Flux with Effector
For our React SPA, we've adopted an "Effector-based Flux architecture" for the following reasons:
1. **Better React Integration**: Flux's unidirectional data flow aligns perfectly with React's rendering model.
2. **Simplicity**: Fewer abstractions and less boilerplate compared to MVVM.
3. **Predictability**: One-way data flow makes it easier to trace how state changes propagate through the application.
4. **Testability**: Pure functions in model.ts are easy to test without complex mocking.
5. **TypeScript Friendly**: Effector has excellent TypeScript support, providing type safety throughout the application.
## Flux Architecture Flow
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Actions │────>│ Store │────>│ View │
│ (Events) │ │ (State) │ │ (React) │
└─────────────┘ └─────────────┘ └─────────────┘
▲ │
│ │
└───────────────────────────────────────┘
User Interaction
```
## Effector Implementation
Effector provides three main primitives that map to Flux concepts:
1. **Events** (Actions): Trigger state changes
```typescript
export const setProductName = createEvent<string>();
```
2. **Stores** (State): Hold application state
```typescript
export const $product = createStore(initialState)
.on(setProductName, (state, name) => ({ ...state, name }));
```
3. **Effects** (Async Actions): Handle side effects
```typescript
export const fetchProductFx = createEffect(async (id: string) => {
return await api.getProduct(id);
});
```
## Conclusion
While MVVM is a valid architecture pattern, Flux with Effector provides a more natural fit for React applications, with less boilerplate and better alignment with React's unidirectional data flow model. This approach keeps our codebase clean, testable, and maintainable.