ciscoheat / deepstate Goto Github PK
View Code? Open in Web Editor NEWAn immutable state container for Haxe 4, similar to Redux.
License: MIT License
An immutable state container for Haxe 4, similar to Redux.
License: MIT License
Hi Andreas!
Noticed something strange when playing around. With the following setup...
typedef State = {
final score:Int;
}
class Asset extends DeepState<State> {
public function new(initialState, middlewares=null) super(initialState, middlewares);
}
...everything works as expected when instantiating the asset as a local variable:
class Main {
static function main() new Main();
public function new() {
var asset = new Asset({score:444}); // <--- Local variable
asset.updateIn(asset.state.score , score->score+1); // Works fine!
trace(asset.state.score);
}
}
However, if I instantiate the asset as a property field of Main, I get "uncaught exception: Error: Field not found in state: asset.state.score":
class Main {
static function main() new Main();
var asset:Asset; // <------------
public function new() {
asset = new Asset({score:444}); <--- Class property
asset.updateIn(asset.state.score , score->score+1); // Error: Field not found...
trace(asset.state.score);
}
}
Is this expected?
Just and idea:
As deepstate isn't a container anymore (rather an instance of the state itself), it maybe could be convenient to include something like a DeepStateContainer in the library? Apart from carrying the asset instance, it could setup a default observable... Actually, mimic the pre 0.4 container api...? :-)
Is there some kind of post-state-change hook where you could wrap something like a mithril.M.redraw()
command?
Any plans for a way to store non-rigid objects, for example a css style object?
Do you somehow keep track of the state history, or are there plans for that?
One of the cool Redux features is the possibility to - via browser plugn - monitor the state changes and to time travel between them...
Something like Reselect for computation of derived data, and memoizing it, would be really useful.
The default level should be "maximum strictness", where the following defines could be used to loosen it up:
-D deepstate-public-update
- will make all the update
methods public, so they can be called from outside an asset. The default is that all update actions must be exposed by public methods in the DeepState<T>
derived class.
I'm not able to define a DC class with anonymous object data.
Neither of these seem to work:
class Example implements DataClass {
public final data1:ds.ImmutableJson;
public final data2:haxe.DynamicAccess<Dynamic>;
}
The first one causes
Unsupported DataClass type: TDynamic
The second one causes
/dataclass/macros/Builder.hx:116: characters 43-44 : Uncaught exception field access on null
Maybe I'm missing something..?
Would there be a possibility to extend the subscribeTo method so that it would act upon change in any of an array of fields? Something like
var unsubscribe = asset.subscribeTo([ asset.state.user, asset.state.article ],
(user, article) -> {
// display or not display article content depending of user's access level...
}
);
Hi again!
I'm getting the following error when trying to use enums in the state object:
src/Main.hx:15: characters 19-35 : Expected enum constructor
src/Main.hx:15: lines 15-17 : Unknown<0> cannot be constructed
No problem in deepstate 0.10.0
Running on Haxe 4.0.0-preview.5 Nightly
Here's the code:
typedef State = {
final test:Test;
final name:String;
}
enum Test {
AltA;
AltB;
}
class Main {
static function main() {
var asset = new DeepState<State>({
test: Test.AltA,
name: 'Jonas',
});
}
}
Right now a Context.typeof
check is done to ensure that a field in the state tree exists and that its type is correct. This could be optimized by storing a map of path => type and test it instead.
We all deal with async nowadays, so some example/suggestion of how to handle this in deepstate would be fine.
(I guess that due to the fact that deepstate doesn't really depend on "actions", async handling is architecturally not really a "deepstate matter"..?)
Would it be possible (as an option?) to let a subscription listener be run/evaluated when attached to the asset object? If so, that could reduce some boilerplate in the view classes.
As an example, here's a simplified view as it looks right now:
class ChapterView extends DomComponent {
var store:AppStore = null;
var user:UserData = null;
var chapter:Chapter = null;
public function new(el:js.html.Element, store:AppStore) {
this.store = store;
// 1. Field data is initially set here...
this.chapter = this.store.state.chapter;
this.user = this.store.state.userState.user;
super(el);
this.store.subscribeTo(this.store.state.chapter,
this.store.state.userState.user,
(chapter, user) -> {
// 2. ...and later, upon further state changes, here:
this.chapter = chapter;
this.user = user;
this.render();
});
}
// View method, à la Mithril
override public function view():OneOf3<String, js.html.Element, Array<js.html.Element>> {
if (this.chapter.access > this.user.access) return m2('div', 'Forbidden access');
return [
m2('h1', this.chapter.title),
m2('p', this.chapter.text),
];
}
}
What "bothers me" is that I have to pluck the state data twice, once initially (// 1.) and once in the subscription listener (//2.) Smells a bit like unnecessary code duplication.
Maybe the subscribe method could have an extra "immediateEvaluation" Bool parameter? If so, the view constructor could look like this:
public function new(el:js.html.Element, store:AppStore) {
this.store = store;
super(el);
this.store.subscribeTo(this.store.state.chapter,
this.store.state.userState.user,
(chapter, user)
-> {
this.chapter = chapter;
this.user = user;
this.render();
}, true); // <- immediateEvaluation set to true
}
Just an idea, to save a few lines of code... What you think?
There is currently no way to add middleware except when constructing the asset object. Would it be useful to be able to add middleware after it has been created?
DeepState doesn't seem to like DataClass objects with fields of it's own type:
class Test implements DataClass {
public final test:Test = null; // <-
}
This causes the compiler to stall.
No big deal for me now, but could cause problem when implementing tree-like structures, lists etc.
There seems to be a runtime problem with when targeting js using Haxe 4 preview 5, released the other day. (--interp works fine!)
At runtime, I get the following:
d:\Dropbox\_dev\fb-stack\dev\_setup-deepstate\public\test.js:292
var ds_Subscription = $hxEnums["ds.Subscription"] = { __ename__ : true, __constructs__ : ["Partial","Full"]
^
ReferenceError: $hxEnums is not defined
at d:\Dropbox\_dev\fb-stack\dev\_setup-deepstate\public\test.js:292:23
at Object.<anonymous> (d:\Dropbox\_dev\fb-stack\dev\_setup-deepstate\public\test.js:317:3)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
at startup (internal/bootstrap/node.js:279:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:696:3)
Error: Command failed with error 1
The terminal process terminated with exit code: 1
hi,
i have a litte question. can be possible observe an aray?
for example
var player_id = 2;
var subscriber = observable.subscribe(
asset.state.players[player_id].name,
name -> trace('Player changed name to ${p.firstName} ${p.name}')
);```
A DC class that is defined using a default value, for example
class Example implements DataClass {
public final id:String = 'defaultBookId';
}
causes the following compile time error:
Unsupported DeepState type for book.title: TLazy(haxe.macro.LazyType)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.