65 lines
2.7 KiB
Markdown
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.
|