MVVM in Frontend Applications
Model-View-ViewModel (MVVM) is an architecture pattern that separates what the UI looks like from the logic that drives it. In React and React Native codebases it maps naturally onto components and custom hooks. The pattern originated at Microsoft; see Model-View-ViewModel for its history.
1. The three layers
| Layer | Owns | Must not |
|---|---|---|
| Model | Domain data, validation, and I/O through services/repositories (API, storage) | Know about UI |
| ViewModel | UI state, derived values, and commands the view can call | Render markup or touch the DOM |
| View | Layout and presentation, binding to the ViewModel | Fetch data or contain business rules |
2. ViewModel as a custom hook
// todos.service.ts (Model / service layer)
export const todosService = {
list: () => api.get('/todos'),
toggle: (id) => api.post(`/todos/${id}/toggle`),
};
// use-todos-view-model.ts (ViewModel)
export function useTodosViewModel() {
const [todos, setTodos] = useState([]);
const [filter, setFilter] = useState('all');
useEffect(() => { todosService.list().then(setTodos); }, []);
const visible = useMemo(
() => todos.filter(t => filter === 'all' || (filter === 'done') === t.done),
[todos, filter],
);
const toggle = useCallback(async (id) => {
setTodos(prev => prev.map(t => t.id === id ? { ...t, done: !t.done } : t));
await todosService.toggle(id);
... premium content.