# dk-mobx-restore-state

> Restores state from initial data object

Latest version **3.5.2** (published 2025-12-01) · MIT license · 0 weekly downloads

## Install

```sh
npm install dk-mobx-restore-state
pnpm add dk-mobx-restore-state
yarn add dk-mobx-restore-state
bun add dk-mobx-restore-state
```

## Health

**Score 60/100 (C)** — status: stable.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 3.5.2 |
| Published | 2025-12-01 |
| First published | 2023-06-25 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 15.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 22 |
| Author | Dmitry Kazakov |
| Maintainers | dkazakov8 |

## Links

- npm: https://www.npmjs.com/package/dk-mobx-restore-state
- Repository: https://github.com/dkazakov8/dk-framework
- Homepage: https://github.com/dkazakov8/dk-framework#readme
- Issues: https://github.com/dkazakov8/dk-framework/issues
- npm.io page: https://npm.io/package/dk-mobx-restore-state

## Recent versions

- 3.5.2 (latest) — 2025-12-01
- 3.5.1 — 2025-10-16
- 3.5.0 — 2025-08-12
- 3.4.13 — 2025-06-02
- 3.4.11 — 2025-04-28
- 3.4.10 — 2024-12-03
- 3.4.5 — 2024-08-08
- 3.4.4 — 2024-07-19
- 3.4.3 — 2024-07-16
- 3.4.2 — 2024-07-12
- 3.4.1 — 2024-06-12
- 3.4.0 — 2024-06-12
- 3.3.9 — 2024-06-05
- 3.3.8 — 2024-06-05
- 3.3.6 — 2024-06-05
- … 69 more at https://npm.io/package/dk-mobx-restore-state/versions

## README

## Library for safe merging of MobX observables

![coverage](https://github.com/dkazakov8/dk-framework/blob/master/packages/mobx-restore-state/cover.svg)
[![npm](https://img.shields.io/npm/v/dk-mobx-restore-state)](https://www.npmjs.com/package/dk-mobx-restore-state)
[![license](https://img.shields.io/npm/l/dk-mobx-restore-state)](https://github.com/dkazakov8/dk-framework/blob/master/packages/mobx-restore-state/LICENSE)
![size](https://github.com/dkazakov8/dk-framework/blob/master/packages/mobx-restore-state/size.svg)

> [!WARNING]  
> It's fine if you use this library from NPM package with a **static versioning** in case you
> want it for some pet-project or to test it's capabilities.
>
> But for production use it's **strongly recommended** to create a fork, because I do not write
> Changelogs and may break / add some functionality without notice.

### Purpose

The purpose of this library is to safely restore state during SSR.

If you want to restore your state and see a problem, it may be as follows:

1. You use MobX 4. It has a bug where newly added objects are not observable, like

```typescript
const result = Object.assign(observable({ str: '123' }), { str: '321', obj: {} });

expect(isObservable(result.obj)).to.eq(false); // BUG in MobX 4
```

Nowadays MobX 5 / 6 versions do not have this bug, we can use `Object.assign`. But when we speak about
classes, the behavior remains inconsistent.

2. You use a class mobx store without enumerated value

```typescript
class Target {
  constructor() { makeAutoObservable(this); }
  str = '123';
}
    
const result = Object.assign(new Target(), { str: '321', obj: {} });

expect(isObservable(result.obj)).to.eq(false); // BUG in all MobX versions
```

3. You use a class mobx store without initial value

```typescript
class Target {
  constructor() { makeAutoObservable(this); }
  str = '123';
  obj?: SomeType;
}
    
const result = Object.assign(new Target(), { str: '321', obj: {} });

expect(isObservable(result.obj)).to.eq(false); // BUG in all MobX versions
```

This is very confusing and depends on transpilers (Babel, TSC, Esbuild, SWC) which all behave
differently. So, this library makes everything **consistent**.

Now that you have fixed these errors and feel happy and still don't want `dk-mobx-restore-state`...

```typescript
class Target {
  constructor() { makeAutoObservable(this); }
  str = '123';
  obj?: SomeType = undefined;
}
    
const result = Object.assign(new Target(), { str: '321', obj: {} });

expect(isObservable(result.obj)).to.eq(true); // No bug finally!
```

4. You come across a problem that `Object.assign` is not a **deep merge**. So you can not restore 
a partial data like

```typescript
class Target {
  constructor() { makeAutoObservable(this); }
  obj = { a: 1 };
}
    
const result = Object.assign(new Target(), { obj: { b: 2 } });

expect(result.obj.a).to.eq(undefined); // Lost some initial data!
```

5. You try `lodash.merge` and see that it merges deeply, but with the same inconsistencies as 
`Object.assign`. You write a customizer and feel happy finally...

```typescript
mergeWith(new Target(), source, (objValue, srcValue) => {
  if (objValue == null && Object.prototype.toString.call(srcValue) === '[object Object]') {
    return observable(srcValue);
  }
}
```

But... There are some edge-cases in the strategy of merging and you need to see the logs of the process...
Actually, you may consider `dk-mobx-restore-state` just from the start. It is thoroughly tested, 1.8kb unminified,
handles most of edge-cases and has no deps.

### Usage

Install `dk-mobx-restore-state` and use it instead of `Object.assign / mergeWith` where needed. Everything
will be `observable` (in MobX 4 or in class objects) in all the cases mentioned above.

#### Syntax

`restoreState({ logs, target, source })`

`logs` (boolean): logging of operations

`target`: object that needs to be filled with observable data

`source`: object with some data (may be observable or not)

---
_Source: https://npm.io/package/dk-mobx-restore-state · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
