/** * Creates a named reactive view and keeps it alive, so that the view is always * updated if one of the dependencies changes, even when the view is not further used by something else. * @param view The reactive view * @returns disposer function, which can be used to stop the view from being updated in the future. */ public static IReactionDisposable Autorun(Action <IReactionPublic> view, IAutorunOptions options = null) { var name = options?.Name ?? $"Autorun@{States.NextId}"; var runSync = options == null || options.Scheduler != null && options.Delay == 0; Reaction _reaction = null; if (runSync) { _reaction = new Reaction(name, (reaction) => { reaction.Track(() => ReactionRunner(reaction)); }, options?.OnError); } else { var scheduler = CreateScheduler(options); // debounced autorun var isScheduled = false; _reaction = new Reaction(name, (reaction) => { if (!isScheduled) { isScheduled = true; scheduler(() => { isScheduled = false; if (!reaction.IsDisposed) { reaction.Track(() => ReactionRunner(reaction)); } }); } }, options?.OnError); } object ReactionRunner(Reaction reaction) { view(reaction); return(null); } _reaction.Schedule(); return(_reaction.GetDisposable()); }
private static Action <Action> CreateScheduler(IAutorunOptions options) { if (options?.Scheduler != null) { return(options.Scheduler); } if (options?.Delay > 0) { return((action) => { SetTimeout(action, options.Delay); }); } return((action) => action()); }
public static IReactionDisposable Autorun(Action view, IAutorunOptions options = null) { return(Autorun(r => view(), options)); }