← Back to blog

Article

React MVVM pattern with DDD

React MVVM pattern with DDD

Introduction

This article is about how to implement MVVM pattern with DDD in React.

MVVM

MVVM is a pattern that separates the data model and business logic from the UI. It is a variation of MVC pattern. The difference between MVC and MVVM is that MVVM has a ViewModel layer that connects the Model and the View. But MVC does not have a ViewModel layer, so the Controller layer connects the Model and the View. The key of MVVM is the data binding between the View and the ViewModel.

Model

Model is a representation of data. It is a layer that contains business logic and data.

View : React Component

View is a layer that represents the UI. It is a layer that contains UI logic.

ViewModel : React Hook to manage state

ViewModel is a layer that connects the Model and the View. It is a layer that contains UI logic and data. Also, ViewModel tracks the changes of the Model and updates the View using React Hook.

DDD pattern (Domain Driven Design pattern)

DDD is a pattern that separates the domain logic from the application logic. It is a pattern that separates the domain logic from the application logic.

Domain

Domain is a layer that contains the business logic. It is a layer that contains the business logic.

Application

Application is a layer that contains the application logic. It is a layer that contains the application logic.

Implementation

Model

// src/model/counter.js
import { observable, action } from 'mobx'

export class Counter {
  @observable count = 0

  @action
  increment() {
    this.count++
  }

  @action
  decrement() {
    this.count--
  }
}

ViewModel

// src/viewModel/counter.js
import { observable, action } from 'mobx'
import { Counter } from '../model/counter'

export class CounterViewModel {
  @observable counter = new Counter()

  @action
  increment() {
    this.counter.increment()
  }

  @action
  decrement() {
    this.counter.decrement()
  }
}

View

// src/view/counter.js
import React from 'react'
import { observer } from 'mobx-react'
import { CounterViewModel } from '../viewModel/counter'

const CounterView = observer(({ viewModel }) => {
  return (
    <div>
      <button onClick={() => viewModel.increment()}>+</button>
      <span>{viewModel.counter.count}</span>
      <button onClick={() => viewModel.decrement()}>-</button>
    </div>
  )
})

export default CounterView

Application

// src/application/counter.js
import { CounterViewModel } from '../viewModel/counter'

export class CounterApplication {
  constructor() {
    this.viewModel = new CounterViewModel()
  }
}

Domain

// src/domain/counter.js
import { CounterApplication } from '../application/counter'

export class CounterDomain {
  constructor() {
    this.application = new CounterApplication()
  }
}

Main

// src/main.js
import React from 'react'
import ReactDOM from 'react-dom'
import { CounterDomain } from './domain/counter'
import CounterView from './view/counter'

const counterDomain = new CounterDomain()

ReactDOM.render(
  <CounterView viewModel={counterDomain.application.viewModel} />,
  document.getElementById('root')
)

Conclusion

This article is about how to implement MVVM pattern with DDD in React.

References

Discussion

Profile picture

Full-Stack Engineer

Yerin Hong

Building products end-to-end across frontend, mobile, backend, and product UX.

Full-stack engineer and generalist. I design, build, and debug products with a bias for clean UX and practical engineering.

© 2026 Yerin Hong

Built with Gatsby