Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/mweststrate/rval
Browse files Browse the repository at this point in the history
  • Loading branch information
mweststrate committed Dec 20, 2018
2 parents b859289 + 8221b3d commit f132766
Show file tree
Hide file tree
Showing 12 changed files with 844 additions and 807 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ dist
.rpt2_cache
.rts2_cache*
/coverage
.docz
.docz
mangle.json
13 changes: 11 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,25 @@
{
// Note; this config requires node 8.4 or higher
"type": "node",
"protocol": "auto",
"protocol": "inspector",
"request": "launch",
"name": "debug unit test - minified",
"stopOnEntry": false,
"program": "${workspaceRoot}/node_modules/jest-cli/bin/jest.js",
"windows": {
"program": "${workspaceRoot}\\node_modules\\jest-cli\\bin\\jest.js"
},
"outFiles": ["pkgs/core/"],
"args": ["--verbose", "--runInBand", "--config", "jest.config.test.json", "-i", "${fileBasename}"],
"runtimeArgs": ["--nolazy"]
"runtimeArgs": ["--nolazy"],
"sourceMaps": true
},
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${file}",
"sourceMaps": true
}
]
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ Todo:
* [ ] rename RvalContext to RvalInstance
* [ ] contributing and debugging
* [ ] support `this.rvalProps(this.rvalProps() + 1)` -> `this.rvalProps(x => x + 1)`?
* [ ] updaters `inc`, `push`, `set`, `delete`, `assign`

* [ ] updaters `inc1`, `inc`, `push`, `set`, `delete`, `assign`, `toggle`
* [ ] utils `assignVals`, `toJS

Later
* [ ] dynamically switch between hook and non-hook implementations (and explain differences)
Expand Down
99 changes: 98 additions & 1 deletion docs/0_introduction/20_objects-and-factories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,101 @@ menu: Introduction
route: /introduction/factories
---

# Objects, factories and the basics of organizing state
# Working with objects and arrays

So far we only used stand-alone reactive values to capture our state.
But in real world applications we will need complex objects or state trees.
But suprisingly, RVal however doesn't offer a primitive to work with objects or array.
Instead:

_consider every object or array as an immutable collection of reactive values_

By keeping objects and arrays themself immutable, it turns out that the mental model remains much simpler,
and the API surface that is needed to apply reactivity is much[^1] smaller.

But, that doesn't RVal is awkward of inconvenient when working with objects.
Instead, it turns out that using objects, which are structurally immutable, but contain stateful reactive values, are presently convenient to work with.

Let's start a bit simple with an object that captures the state of a `Todo` item (with apologies for the uninspired example):

```javascript
const title = val('Get coffee')
const done = val(false)

const myFirstTodo = {
title,
done,
}

title.done(true)
console.log(title.done())
```

Pretty straight forward eh? Note that we used only `const` values, and that `myFirstTodo` itself should be treated as an immutable objects to keep the conceptuel model simple.
(In fact, it would be recommended to use `Object.freeze(myFirstTodo)`, but it turns out that RVal will take care of that as well in most cases, as we will discover later).

## A first object factory

Probably you don't want to create multiple todo's in your application, intead of one.
To ease that process we can make a _factory_ funtion:

```javascript
function createTodo(initialTitle) {
const title = val(initialTitle)
const done = val(false)
return {
title,
done,
}
}

const myFirstTodo = createTodo("Get coffee")
myFirstTodo.done(true)
```

Ok, that was easy! But our factory function can do more than just instating some reactive values and combining them into an object.
We can add define derived data using `drv`, and actions using `act`, and make them part of the object as well:

```javascript
function createTodo(initialTitle) {
const title = val(initialTitle)
const done = val(false)
const asMarkdown(() => done() ? " * [x] ~" + title() + "~" : " * [ ] " +title())
const toggle = act(() {
done(!done())
})

return {
title, done, toggle, asMarkdown
}
}
```

So, we now have a factory that creates an immutable object, containing some reactive values, derivations and actions.
Note that we are only creating `const`s in these listing, and we neatly avoided using `this`, which might save some headaches down the road![^2]

Let's put our code to the test and create a `sub` to observe the effects of our state updates:

```javascript
const myFirstTodo = createTodo("Get coffee")
sub(myFirstTodo.asMarkdown, md => {
console.log(md)
}

myFirstTodo.title("Get coffee and cookie")
// Prints: * [ ] Get coffee and cookie

myFirstTodo.toggle()
// Prints: * [x] ~Get coffee and cookie~
```
## Combining factories
## Using classes
Freezing
[^1]: In MobX, roughly 75% of the code base is dealing with decorators, making plain data structures observable and dealing with the various different ways that people have to work with objects.
[^2]: For _super_ performance critical applications (measure before optimizing!), one could use `Object.create` and store actions on the `prototype`, leveraging `this` and avoid creating a closure per action per instance.
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@
],
"devDependencies": {
"@types/jest": "^23.3.9",
"@types/node": "^10.12.10",
"@types/node": "^10.12.17",
"@types/react": "^16.7.17",
"@types/react-dom": "^16.0.11",
"coveralls": "^3.0.2",
"cross-env": "^5.2.0",
"docz": "^0.12.17",
"docz-theme-default": "^0.12.17",
"immer": "^1.8.0",
"docz": "^0.13.4",
"docz-theme-default": "^0.13.4",
"immer": "^1.9.3",
"jest": "^23.6.0",
"microbundle": "^0.8.3",
"microbundle": "^0.9.0",
"prettier": "^1.15.2",
"react": "^16.7.0-alpha.2",
"react-dom": "^16.7.0-alpha.2",
"react-testing-library": "^5.4.0",
"rimraf": "^2.6.2",
"rollup": "^0.67.4",
"rollup": "^0.68.0",
"rollup-plugin-filesize": "^5.0.1",
"rollup-plugin-terser": "^3.0.0",
"rollup-plugin-typescript2": "^0.18.0",
Expand Down
38 changes: 31 additions & 7 deletions pkgs/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,41 @@
"description": "",
"main": "dist/core.js",
"umd:main": "dist/core.umd.js",
"unpkg": "dist/core.umd.js",
"module": "dist/core.mjs",
"source": "core.ts",
"scripts": {
"jsnext:main": "dist/core.mjs",
"react-native": "dist/core.mjs",
"browser": {
"./dist/core.js": "./dist/core.js",
"./dist/core.mjs": "./dist/core.mjs"
},
"source": "core.ts",
"scripts": {},
"author": "Michel Weststrate",
"license": "MIT",
"dependencies": {},
"files": [
"*.ts",
"dist"
],
"devDependencies": {
"files": ["*.ts", "dist"],
"devDependencies": {},
"mangle": {
"reserved": [
"val",
"drv",
"sub",
"batch",
"batched",
"deepfreeze",
"isVal",
"isDrv",
"defaultContext",
"rval",
"rview",
"useVal",
"useLocalVal",
"useLocalDrv",
"model",
"mapOf",
"arrayOf",
"updater"
]
}
}
38 changes: 31 additions & 7 deletions pkgs/immer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,41 @@
"description": "",
"main": "dist/immer.js",
"umd:main": "dist/immer.umd.js",
"unpkg": "dist/immer.umd.js",
"module": "dist/immer.mjs",
"source": "immer.ts",
"scripts": {
"jsnext:main": "dist/immer.mjs",
"react-native": "dist/immer.mjs",
"browser": {
"./dist/immer.js": "./dist/immer.js",
"./dist/immer.mjs": "./dist/immer.mjs"
},
"source": "immer.ts",
"scripts": {},
"author": "Michel Weststrate",
"license": "MIT",
"dependencies": {},
"files": [
"*.ts",
"dist"
],
"devDependencies": {
"files": ["*.ts", "dist"],
"devDependencies": {},
"mangle": {
"reserved": [
"val",
"drv",
"sub",
"batch",
"batched",
"deepfreeze",
"isVal",
"isDrv",
"defaultContext",
"rval",
"rview",
"useVal",
"useLocalVal",
"useLocalDrv",
"model",
"mapOf",
"arrayOf",
"updater"
]
}
}
38 changes: 31 additions & 7 deletions pkgs/models/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,41 @@
"description": "",
"main": "dist/models.js",
"umd:main": "dist/models.umd.js",
"unpkg": "dist/models.umd.js",
"module": "dist/models.mjs",
"source": "models.ts",
"scripts": {
"jsnext:main": "dist/models.mjs",
"react-native": "dist/models.mjs",
"browser": {
"./dist/models.js": "./dist/models.js",
"./dist/models.mjs": "./dist/models.mjs"
},
"source": "models.ts",
"scripts": {},
"author": "Michel Weststrate",
"license": "MIT",
"dependencies": {},
"files": [
"*.ts",
"dist"
],
"devDependencies": {
"files": ["*.ts", "dist"],
"devDependencies": {},
"mangle": {
"reserved": [
"val",
"drv",
"sub",
"batch",
"batched",
"deepfreeze",
"isVal",
"isDrv",
"defaultContext",
"rval",
"rview",
"useVal",
"useLocalVal",
"useLocalDrv",
"model",
"mapOf",
"arrayOf",
"updater"
]
}
}
38 changes: 31 additions & 7 deletions pkgs/package-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,41 @@
"description": "minimalistic transparent reactive programming library",
"main": "dist/$pkg.js",
"umd:main": "dist/$pkg.umd.js",
"unpkg": "dist/$pkg.umd.js",
"module": "dist/$pkg.mjs",
"source": "$pkg.ts",
"scripts": {
"jsnext:main": "dist/$pkg.mjs",
"react-native": "dist/$pkg.mjs",
"browser": {
"./dist/$pkg.js": "./dist/$pkg.js",
"./dist/$pkg.mjs": "./dist/$pkg.mjs"
},
"source": "$pkg.ts",
"scripts": {},
"author": "Michel Weststrate",
"license": "MIT",
"dependencies": {},
"files": [
"*.ts",
"dist"
],
"devDependencies": {
"files": ["*.ts", "dist"],
"devDependencies": {},
"mangle": {
"reserved": [
"val",
"drv",
"sub",
"batch",
"batched",
"deepfreeze",
"isVal",
"isDrv",
"defaultContext",
"rval",
"rview",
"useVal",
"useLocalVal",
"useLocalDrv",
"model",
"mapOf",
"arrayOf",
"updater"
]
}
}
Loading

0 comments on commit f132766

Please sign in to comment.