public void ShouldBePossibleToChangeObservedStateInActionCalledFromComputedIfRunInsideAllowStateChange() { var a = this.sharedState.Box(2); var d = this.sharedState.Autorun(r => { int i = a.Value; }); IComputedValue <int> c = null; IComputedValue <int> c2 = null; var testAction = this.sharedState.CreateAction(() => { this.sharedState.AllowStateChangesInsideComputed(() => { a.Value = 3; Assert.Throws <InvalidOperationException>(() => { // Computed values are not allowed to cause side effects by // changing observables that are already being observed int i = c2.Value; }); return(0); }); Assert.Equal(3, a.Value); Assert.Throws <InvalidOperationException>(() => { // Computed values are not allowed to cause side effects by // changing observables that are already being observed/ a.Value = 4; }); }); c = this.sharedState.Computed( () => { testAction(); return(a.Value); }, "computed"); c2 = this.sharedState.Computed( () => { a.Value = 6; return(a.Value); }, "computed"); int j = c.Value; d.Dispose(); }
public void TestAllowModificationInComputed() { var a = ObservableValue <int> .From(2); var d = Reactions.Autorun(() => { var x = a.Value; }); IComputedValue <int> c2 = null; var action = Actions.CreateAction("action", () => { Actions.AllowStateChangesInsideComputed(() => { a.Value = 3; //// a second level computed should throw Assert.Throws <CaughtException>(() => { // /Computed values are not allowed to cause side effects by changing observables that are already being observed/ var x = c2.Value; }); }); Assert.Equal(3, a.Value); Assert.Throws <Exception>(() => { // /Computed values are not allowed to cause side effects by changing observables that are already being observed/ a.Value = 4; }); }); var c = ComputedValue <int> .From(() => { action(); return(a.Value); }); c2 = ComputedValue <int> .From(() => { a.Value = 6; return(a.Value); }); var _ = c.Value; d.Dispose(); }
public TodoStore(HTMLElement root) { // Render UI elements: Render(root); // Subscribe to Todos changes: _todos.observe(TodoObserveFn); // Configure computed field (_completedTodosCount): _completedTodosCount = computed.Self(() => _todos.filter((v, i, arr) => v.Completed ? (object)true : null).Length); // Configure computed field (_report): _report = computed.Self(() => $"Progress: {CompletedTodosCount}/{_todos.length}"); // Configure reaction on state changes: autorun(StageChangedFn); }
internal StoredReference(StoreType type, object value, IType targetType) { Type = type; Value = value; TargetType = targetType; if (Type == StoreType.Object) { if (!value.IsStateTreeNode()) { throw new ArgumentException($"Can only store references to tree nodes, got: '{value}'"); } var node = value.GetStateTreeNode(); if (string.IsNullOrWhiteSpace(node.IdentifierAttribute)) { throw new ArgumentException("Can only store references with a defined identifier attribute."); } } _resolvedValue = ComputedValue <object> .From(() => { var identifier = Value?.ToString(); if (string.IsNullOrWhiteSpace(identifier)) { return(null); } // reference was initialized with the identifier of the target var target = Node.Root.IdentifierCache?.Resolve(TargetType, identifier); if (target == null) { throw new Exception($"Failed to resolve reference '{identifier}' to type '{TargetType.Name}' (from node: {Node.Path})"); } return(target?.Value); }); }