updux/docs/index.html
2019-11-05 19:47:27 -05:00

410 lines
23 KiB
HTML

<!doctype html>
<html class="default no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>updux</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="assets/css/main.css">
</head>
<body>
<header>
<div class="tsd-page-toolbar">
<div class="container">
<div class="table-wrap">
<div class="table-cell" id="tsd-search" data-index="assets/js/search.js" data-base=".">
<div class="field">
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
<input id="tsd-search-field" type="text" />
</div>
<ul class="results">
<li class="state loading">Preparing search index...</li>
<li class="state failure">The search index is not available</li>
</ul>
<a href="index.html" class="title">updux</a>
</div>
<div class="table-cell" id="tsd-widgets">
<div id="tsd-filter">
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
<div class="tsd-filter-group">
<div class="tsd-select" id="tsd-filter-visibility">
<span class="tsd-select-label">All</span>
<ul class="tsd-select-list">
<li data-value="public">Public</li>
<li data-value="protected">Public/Protected</li>
<li data-value="private" class="selected">All</li>
</ul>
</div>
<input type="checkbox" id="tsd-filter-inherited" checked />
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
<input type="checkbox" id="tsd-filter-externals" checked />
<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
<input type="checkbox" id="tsd-filter-only-exported" />
<label class="tsd-widget" for="tsd-filter-only-exported">Only exported</label>
</div>
</div>
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
</div>
</div>
</div>
</div>
<div class="tsd-page-title">
<div class="container">
<ul class="tsd-breadcrumb">
<li>
<a href="globals.html">Globals</a>
</li>
</ul>
<h1> updux</h1>
</div>
</div>
</header>
<div class="container container-main">
<div class="row">
<div class="col-8 col-content">
<div class="tsd-panel tsd-typography">
<a href="#what39s-updux" id="what39s-updux" style="color: inherit; text-decoration: none;">
<h1>What&#39;s Updux?</h1>
</a>
<p>So, I&#39;m a fan of <a href="https://redux.js.org">Redux</a>. Two days ago I discovered
<a href="https://rematch.github.io/rematch">rematch</a> alonside a few other frameworks built atop Redux. </p>
<p>It has a couple of pretty good ideas that removes some of the
boilerplate. Keeping mutations and asynchronous effects close to the
reducer definition? Nice. Automatically infering the
actions from the said mutations and effects? Genius!</p>
<p>But it also enforces a flat hierarchy of reducers -- where
is the fun in that? And I&#39;m also having a strong love for
<a href="https://github.com/substantial/updeep">Updeep</a>, so I want reducer state updates to leverage the heck out of it.</p>
<p>All that to say, say hello to <code>Updux</code>. Heavily inspired by <code>rematch</code>, but twisted
to work with <code>updeep</code> and to fit my peculiar needs. It offers features such as</p>
<ul>
<li>Mimic the way VueX has mutations (reducer reactions to specific actions) and
effects (middleware reacting to actions that can be asynchronous and/or
have side-effects), so everything pertaining to a store are all defined
in the space place.</li>
<li>Automatically gather all actions used by the updux&#39;s effects and mutations,
and makes then accessible as attributes to the <code>dispatch</code> object of the
store.</li>
<li>Mutations have a signature that is friendly to Updux and Immer.</li>
<li>Also, the mutation signature auto-unwrap the payload of the actions for you.</li>
<li>TypeScript types.</li>
</ul>
<p>Fair warning: this package is still very new, probably very buggy,
definitively very badly documented, and very subject to changes. Caveat
Maxima Emptor.</p>
<a href="#synopsis" id="synopsis" style="color: inherit; text-decoration: none;">
<h1>Synopsis</h1>
</a>
<pre><code><span class="hljs-keyword">import</span> updux <span class="hljs-keyword">from</span> <span class="hljs-string">'updux'</span>;
<span class="hljs-keyword">import</span> otherUpdux <span class="hljs-keyword">from</span> <span class="hljs-string">'./otherUpdux'</span>;
<span class="hljs-keyword">const</span> {
initial,
reducer,
actions,
middleware,
createStore,
} = <span class="hljs-keyword">new</span> Updux({
<span class="hljs-attr">initial</span>: {
<span class="hljs-attr">counter</span>: <span class="hljs-number">0</span>,
},
<span class="hljs-attr">subduxes</span>: {
otherUpdux,
},
<span class="hljs-attr">mutations</span>: {
<span class="hljs-attr">inc</span>: <span class="hljs-function">(<span class="hljs-params"> increment = <span class="hljs-number">1</span> </span>) =&gt;</span> u({<span class="hljs-attr">counter</span>: <span class="hljs-function"><span class="hljs-params">s</span> =&gt;</span> s + increment })
},
<span class="hljs-attr">effects</span>: {
<span class="hljs-string">'*'</span> =&gt; <span class="hljs-function"><span class="hljs-params">api</span> =&gt;</span> <span class="hljs-function"><span class="hljs-params">next</span> =&gt;</span> <span class="hljs-function"><span class="hljs-params">action</span> =&gt;</span> {
<span class="hljs-built_in">console</span>.log( <span class="hljs-string">"hey, look, an action zoomed by!"</span>, action );
next(action);
};
},
<span class="hljs-attr">actions</span>: {
<span class="hljs-attr">customAction</span>: <span class="hljs-function">(<span class="hljs-params"> someArg </span>) =&gt;</span> ({
<span class="hljs-attr">type</span>: <span class="hljs-string">"custom"</span>,
<span class="hljs-attr">payload</span>: { <span class="hljs-attr">someProp</span>: someArg }
}),
},
});
<span class="hljs-keyword">const</span> store = createStore();
store.dispatch.inc(<span class="hljs-number">3</span>);</code></pre>
<a href="#description" id="description" style="color: inherit; text-decoration: none;">
<h1>Description</h1>
</a>
<p>The formal documentation of the class Updux and its associated functions and
types can be found over <a href="https://yanick.github.io/updux/docs/classes/updux.html">here</a>.</p>
<a href="#exporting-upduxes" id="exporting-upduxes" style="color: inherit; text-decoration: none;">
<h2>Exporting upduxes</h2>
</a>
<p>If you are creating upduxes that will be used as subduxes
by other upduxes, or as
<a href="https://github.com/erikras/ducks-modular-redux">ducks</a>-like containers, I
recommend that you export the Updux instance as the default export:</p>
<pre><code>import Updux <span class="hljs-keyword">from</span> <span class="hljs-string">'updux'</span>;
const updux = new Updux({ <span class="hljs-built_in">..</span>. });
<span class="hljs-builtin-name">export</span><span class="hljs-built_in"> default </span>updux;</code></pre><p>Then you can use them as subduxes like this:</p>
<pre><code><span class="hljs-keyword">import</span> Updux <span class="hljs-keyword">from</span> <span class="hljs-string">'updux'</span>;
<span class="hljs-keyword">import</span> foo <span class="hljs-keyword">from</span> <span class="hljs-string">'./foo'</span>; <span class="hljs-comment">// foo is an Updux</span>
<span class="hljs-keyword">import</span> bar <span class="hljs-keyword">from</span> <span class="hljs-string">'./bar'</span>; <span class="hljs-comment">// bar is an Updux as well</span>
<span class="hljs-keyword">const</span> updux = <span class="hljs-keyword">new</span> Updux({
<span class="hljs-attr">subduxes</span>: {
foo, bar
}
});</code></pre><p>Or if you want to use it:</p>
<pre><code><span class="hljs-keyword">import</span> updux <span class="hljs-keyword">from</span> <span class="hljs-string">'./myUpdux'</span>;
<span class="hljs-keyword">const</span> {
reducer,
<span class="hljs-attr">actions</span>: { doTheThing },
createStore,
middleware,
} = updux;</code></pre>
<a href="#mapping-a-mutation-to-all-values-of-a-state" id="mapping-a-mutation-to-all-values-of-a-state" style="color: inherit; text-decoration: none;">
<h2>Mapping a mutation to all values of a state</h2>
</a>
<p>Say you have a <code>todos</code> state that is an array of <code>todo</code> sub-states. It&#39;s easy
enough to have the main reducer maps away all items to the sub-reducer:</p>
<pre><code>const todo = <span class="hljs-keyword">new</span> Updux({
mutations: {
review: <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> u({ reviewed: <span class="hljs-literal">true</span>}),
done: <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> u({done: <span class="hljs-literal">true</span>}),
},
});
const todos = <span class="hljs-keyword">new</span> Updux({ initial: [] });
todos.addMutation(
todo.actions.review,
<span class="hljs-function"><span class="hljs-params">(_,action)</span> =&gt;</span> state =&gt; state.map( todo.upreducer(action) )
);
todos.addMutation(
todo.actions.done,
<span class="hljs-function"><span class="hljs-params">(id,action)</span> =&gt;</span> u.map(u.<span class="hljs-keyword">if</span>(u.<span class="hljs-keyword">is</span>(<span class="hljs-string">'id'</span>,id), todo.upreducer(action))),
);
</code></pre><p>But <code>updeep</code> can iterate through all the items of an array (or the values of
an object) via the special key <code>*</code>. So the todos updux above could also be
written:</p>
<pre><code>const todo = <span class="hljs-keyword">new</span> Updux({
mutations: {
review: <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> u({ reviewed: <span class="hljs-literal">true</span>}),
done: <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> u({done: <span class="hljs-literal">true</span>}),
},
});
const todos = <span class="hljs-keyword">new</span> Updux({
subduxes: { <span class="hljs-string">'*'</span>: todo },
});
todos.addMutation(
todo.actions.done,
<span class="hljs-function"><span class="hljs-params">(id,action)</span> =&gt;</span> u.map(u.<span class="hljs-keyword">if</span>(u.<span class="hljs-keyword">is</span>(<span class="hljs-string">'id'</span>,id), todo.upreducer(action))),
<span class="hljs-literal">true</span>
);</code></pre><p>The advantages being that the actions/mutations/effects of the subdux will be
imported by the root updux as usual, and all actions that aren&#39;t being
overridden by a sink mutation will trickle down automatically.</p>
<a href="#usage-with-immer" id="usage-with-immer" style="color: inherit; text-decoration: none;">
<h2>Usage with Immer</h2>
</a>
<p>While Updux was created with Updeep in mind, it also plays very
well with <a href="https://immerjs.github.io/immer/docs/introduction">Immer</a>.</p>
<p>For example, taking this basic updux:</p>
<pre><code><span class="hljs-keyword">import</span> Updux <span class="hljs-keyword">from</span> <span class="hljs-string">'updux'</span>;
<span class="hljs-keyword">const</span> updux = <span class="hljs-keyword">new</span> Updux({
<span class="hljs-attr">initial</span>: { <span class="hljs-attr">counter</span>: <span class="hljs-number">0</span> },
<span class="hljs-attr">mutations</span>: {
<span class="hljs-attr">add</span>: <span class="hljs-function">(<span class="hljs-params">inc=<span class="hljs-number">1</span></span>) =&gt;</span> <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> { <span class="hljs-attr">counter</span>: counter + inc }
}
});
</code></pre><p>Converting it to Immer would look like:</p>
<pre><code><span class="hljs-keyword">import</span> Updux <span class="hljs-keyword">from</span> <span class="hljs-string">'updux'</span>;
<span class="hljs-keyword">import</span> { produce } <span class="hljs-keyword">from</span> <span class="hljs-string">'Immer'</span>;
<span class="hljs-keyword">const</span> updux = <span class="hljs-keyword">new</span> Updux({
<span class="hljs-attr">initial</span>: { <span class="hljs-attr">counter</span>: <span class="hljs-number">0</span> },
<span class="hljs-attr">mutations</span>: {
<span class="hljs-attr">add</span>: <span class="hljs-function">(<span class="hljs-params">inc=<span class="hljs-number">1</span></span>) =&gt;</span> produce( <span class="hljs-function"><span class="hljs-params">draft</span> =&gt;</span> draft.counter += inc ) }
}
});
</code></pre><p>But since typing <code>produce</code> over and over is no fun, <code>groomMutations</code>
can be used to wrap all mutations with it:</p>
<pre><code><span class="hljs-keyword">import</span> Updux <span class="hljs-keyword">from</span> <span class="hljs-string">'updux'</span>;
<span class="hljs-keyword">import</span> { produce } <span class="hljs-keyword">from</span> <span class="hljs-string">'Immer'</span>;
<span class="hljs-keyword">const</span> updux = <span class="hljs-keyword">new</span> Updux({
<span class="hljs-attr">initial</span>: { <span class="hljs-attr">counter</span>: <span class="hljs-number">0</span> },
<span class="hljs-attr">groomMutations</span>: <span class="hljs-function"><span class="hljs-params">mutation</span> =&gt;</span> <span class="hljs-function">(<span class="hljs-params">...args</span>) =&gt;</span> produce( mutation(...args) ),
<span class="hljs-attr">mutations</span>: {
<span class="hljs-attr">add</span>: <span class="hljs-function">(<span class="hljs-params">inc=<span class="hljs-number">1</span></span>) =&gt;</span> <span class="hljs-function"><span class="hljs-params">draft</span> =&gt;</span> draft.counter += inc
}
});
</code></pre>
</div>
</div>
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
<nav class="tsd-navigation primary">
<ul>
<li class="globals ">
<a href="globals.html"><em>Globals</em></a>
</li>
</ul>
</nav>
<nav class="tsd-navigation secondary menu-sticky">
<ul class="before-current">
<li class=" tsd-kind-class tsd-has-type-parameter">
<a href="classes/updux.html" class="tsd-kind-icon">Updux</a>
</li>
<li class=" tsd-kind-type-alias tsd-has-type-parameter">
<a href="globals.html#action" class="tsd-kind-icon">Action</a>
</li>
<li class=" tsd-kind-type-alias tsd-has-type-parameter">
<a href="globals.html#actioncreator" class="tsd-kind-icon">Action<wbr>Creator</a>
</li>
<li class=" tsd-kind-type-alias tsd-is-not-exported">
<a href="globals.html#actionpair" class="tsd-kind-icon">Action<wbr>Pair</a>
</li>
<li class=" tsd-kind-type-alias">
<a href="globals.html#actionpayloadgenerator" class="tsd-kind-icon">Action<wbr>Payload<wbr>Generator</a>
</li>
<li class=" tsd-kind-type-alias tsd-has-type-parameter">
<a href="globals.html#dictionary" class="tsd-kind-icon">Dictionary</a>
</li>
<li class=" tsd-kind-type-alias tsd-has-type-parameter">
<a href="globals.html#dux" class="tsd-kind-icon">Dux</a>
</li>
<li class=" tsd-kind-type-alias tsd-has-type-parameter tsd-is-not-exported">
<a href="globals.html#maybepayload" class="tsd-kind-icon">Maybe<wbr>Payload</a>
</li>
<li class=" tsd-kind-type-alias tsd-has-type-parameter">
<a href="globals.html#mutation" class="tsd-kind-icon">Mutation</a>
</li>
<li class=" tsd-kind-type-alias tsd-is-not-exported">
<a href="globals.html#next" class="tsd-kind-icon">Next</a>
</li>
<li class=" tsd-kind-type-alias tsd-has-type-parameter tsd-is-not-exported">
<a href="globals.html#storewithdispatchactions" class="tsd-kind-icon">Store<wbr>With<wbr>Dispatch<wbr>Actions</a>
</li>
<li class=" tsd-kind-type-alias tsd-is-not-exported">
<a href="globals.html#submutations" class="tsd-kind-icon">Sub<wbr>Mutations</a>
</li>
<li class=" tsd-kind-type-alias tsd-has-type-parameter">
<a href="globals.html#upduxconfig" class="tsd-kind-icon">Updux<wbr>Config</a>
</li>
<li class=" tsd-kind-type-alias">
<a href="globals.html#upduxdispatch" class="tsd-kind-icon">Updux<wbr>Dispatch</a>
</li>
<li class=" tsd-kind-type-alias tsd-has-type-parameter">
<a href="globals.html#upreducer" class="tsd-kind-icon">Upreducer</a>
</li>
<li class=" tsd-kind-function tsd-is-not-exported">
<a href="globals.html#middlewarefor" class="tsd-kind-icon">Middleware<wbr>For</a>
</li>
<li class=" tsd-kind-function tsd-has-type-parameter">
<a href="globals.html#actioncreator" class="tsd-kind-icon">action<wbr>Creator</a>
</li>
<li class=" tsd-kind-function tsd-is-not-exported">
<a href="globals.html#actionfor" class="tsd-kind-icon">action<wbr>For</a>
</li>
<li class=" tsd-kind-function">
<a href="globals.html#buildactions" class="tsd-kind-icon">build<wbr>Actions</a>
</li>
<li class=" tsd-kind-function tsd-has-type-parameter">
<a href="globals.html#buildcreatestore" class="tsd-kind-icon">build<wbr>Create<wbr>Store</a>
</li>
<li class=" tsd-kind-function tsd-has-type-parameter">
<a href="globals.html#buildinitial" class="tsd-kind-icon">build<wbr>Initial</a>
</li>
<li class=" tsd-kind-function tsd-has-type-parameter">
<a href="globals.html#buildmiddleware" class="tsd-kind-icon">build<wbr>Middleware</a>
</li>
<li class=" tsd-kind-function">
<a href="globals.html#buildmutations" class="tsd-kind-icon">build<wbr>Mutations</a>
</li>
<li class=" tsd-kind-function tsd-has-type-parameter">
<a href="globals.html#buildupreducer" class="tsd-kind-icon">build<wbr>Upreducer</a>
</li>
<li class=" tsd-kind-function tsd-is-not-exported">
<a href="globals.html#composemutations" class="tsd-kind-icon">compose<wbr>Mutations</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<footer class="with-border-bottom">
<div class="container">
<h2>Legend</h2>
<div class="tsd-legend-group">
<ul class="tsd-legend">
<li class="tsd-kind-module"><span class="tsd-kind-icon">Module</span></li>
<li class="tsd-kind-object-literal"><span class="tsd-kind-icon">Object literal</span></li>
<li class="tsd-kind-variable"><span class="tsd-kind-icon">Variable</span></li>
<li class="tsd-kind-function"><span class="tsd-kind-icon">Function</span></li>
<li class="tsd-kind-function tsd-has-type-parameter"><span class="tsd-kind-icon">Function with type parameter</span></li>
<li class="tsd-kind-index-signature"><span class="tsd-kind-icon">Index signature</span></li>
<li class="tsd-kind-type-alias"><span class="tsd-kind-icon">Type alias</span></li>
<li class="tsd-kind-type-alias tsd-has-type-parameter"><span class="tsd-kind-icon">Type alias with type parameter</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-enum"><span class="tsd-kind-icon">Enumeration</span></li>
<li class="tsd-kind-enum-member"><span class="tsd-kind-icon">Enumeration member</span></li>
<li class="tsd-kind-property tsd-parent-kind-enum"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-enum"><span class="tsd-kind-icon">Method</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-interface"><span class="tsd-kind-icon">Interface</span></li>
<li class="tsd-kind-interface tsd-has-type-parameter"><span class="tsd-kind-icon">Interface with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-interface"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-interface"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-interface"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-class"><span class="tsd-kind-icon">Class</span></li>
<li class="tsd-kind-class tsd-has-type-parameter"><span class="tsd-kind-icon">Class with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class"><span class="tsd-kind-icon">Accessor</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-class"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static property</span></li>
<li class="tsd-kind-call-signature tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static method</span></li>
</ul>
</div>
</div>
</footer>
<div class="container tsd-generator">
<p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p>
</div>
<div class="overlay"></div>
<script src="assets/js/main.js"></script>
<script>if (location.protocol == 'file:') document.write('<script src="assets/js/search.js"><' + '/script>');</script>
</body>
</html>