UNPKG

redux-actions-promise-wrapper

Version:

Type safe wrapper for redux actions (compatible with redux-saga)

363 lines (339 loc) 17.8 kB
<!doctype html> <html class="default no-js"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>my-project-name</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">my-project-name</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> my-project-name</h1> </div> </div> </header> <div class="container container-main"> <div class="row"> <div class="col-8 col-content"> <div class="tsd-panel tsd-typography"> <p><a href="https://travis-ci.org/thu-san/redux-actions-promise-wrapper"><img src="https://travis-ci.org/thu-san/redux-actions-promise-wrapper.svg?branch=master" alt="Build Status"></a> <a href="https://coveralls.io/github/thu-san/redux-actions-promise-wrapper?branch=master"><img src="https://coveralls.io/repos/github/thu-san/redux-actions-promise-wrapper/badge.svg?branch=master" alt="Coverage Status"></a></p> <h1 id="redux-actions-promise-wrapper">redux-actions-promise-wrapper</h1> <p>Type safe redux action creator (works with redux saga)</p> <h2 id="installation">Installation</h2> <pre><code class="language-sh">npm install redux-actions-promise-wrapper --save yarn add redux-actions-promise-wrapper bower install redux-actions-promise-wrapper --save</code></pre> <h2 id="feature">Feature</h2> <p>Create type safe action creators and enable callback for redux saga.</p> <h2 id="example-project">Example Project</h2> <p><a href="https://github.com/thu-san/redux-actions-promise-wrapper-usage-example">https://github.com/thu-san/redux-actions-promise-wrapper-usage-example</a></p> <h2 id="usage">Usage</h2> <h3 id="typescript">TypeScript</h3> <h5 id="create-action">Create Action</h5> <pre><code class="language-typescript"><span class="hljs-keyword">import</span> { createAction } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-actions-promise-wrapper'</span>; <span class="hljs-keyword">const</span> login = createAction(<span class="hljs-string">'LOGIN/TRIGGER'</span>, <span class="hljs-string">'LOGIN/SUCCESS'</span>, <span class="hljs-string">'LOGIN/FAILURE'</span>)&lt; { email: <span class="hljs-built_in">string</span>; password: <span class="hljs-built_in">string</span>; }, { session: <span class="hljs-built_in">string</span>; } &gt;();</code></pre> <p><code>login</code> now contains the following properties</p> <pre><code class="language-typescript">login.TRIGGER = <span class="hljs-string">'LOGIN/TRIGGER'</span>; login.SUCCESS = <span class="hljs-string">'LOGIN/SUCCESS'</span>; login.FAILURE = <span class="hljs-string">'LOGIN/FAILURE'</span>; login.trigger(payload) === { <span class="hljs-keyword">type</span>: <span class="hljs-string">'LOGIN/TRIGGER'</span>, payload }; <span class="hljs-comment">// payload must have type { email: string, password: string }</span> login.success(payload) === { <span class="hljs-keyword">type</span>: <span class="hljs-string">'LOGIN/SUCCESS'</span>, payload }; <span class="hljs-comment">// payload must have type { session: string }</span> login.failure() === { <span class="hljs-keyword">type</span>: <span class="hljs-string">'LOGIN/FAILURE'</span> }; login(payload) === login.trigger(payload); You can also call on login <span class="hljs-keyword">for</span> trigger action.</code></pre> <h4 id="redux-saga-example">Redux Saga Example</h4> <h5 id="types-saga-and-reducer">Types, Saga and Reducer</h5> <pre><code class="language-typescript"><span class="hljs-comment">// TYPES</span> <span class="hljs-keyword">interface</span> ILoginTriggerPayload { account: <span class="hljs-built_in">string</span>; } <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> loginAction = createAction(<span class="hljs-string">'LOGIN/TRIGGER'</span>, <span class="hljs-string">'LOGIN/SUCCESS'</span>)( handleLogin, <span class="hljs-function"><span class="hljs-keyword">function</span>*(<span class="hljs-params">arg: { session: <span class="hljs-built_in">string</span>; account: <span class="hljs-built_in">string</span> }</span>) </span>{ <span class="hljs-keyword">return</span> <span class="hljs-literal">undefined</span>; } ); <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> logoutAction = createAction(<span class="hljs-string">'LOGOUT/TRIGGER'</span>)&lt;{ session: <span class="hljs-built_in">string</span>; }&gt;(); <span class="hljs-comment">// SAGA</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">handleLogin</span>(<span class="hljs-params">{ account }: ILoginTriggerPayload</span>) </span>{ <span class="hljs-keyword">yield</span> delay(<span class="hljs-number">1000</span>); <span class="hljs-keyword">const</span> putLoginSuccess = put( loginAction.success({ session: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toString(), account }) ); <span class="hljs-keyword">yield</span> putLoginSuccess; <span class="hljs-keyword">return</span> reg(account); } <span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span>* <span class="hljs-title">authSaga</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">yield</span> all([takeLatest(loginAction.TRIGGER, loginAction.handleTrigger)]); } <span class="hljs-comment">// REDUCER</span> <span class="hljs-keyword">interface</span> IAuth { account?: <span class="hljs-built_in">string</span>; session?: <span class="hljs-built_in">string</span>; } <span class="hljs-keyword">const</span> INITIAL_STATE: IAuth = {}; <span class="hljs-keyword">type</span> Actions = ExtractActions&lt;{ loginAction: <span class="hljs-keyword">typeof</span> loginAction; logoutAction: <span class="hljs-keyword">typeof</span> logoutAction; }&gt;; <span class="hljs-keyword">const</span> reducer: Reducer&lt;IAuth, Actions&gt; = <span class="hljs-function">(<span class="hljs-params">state = INITIAL_STATE, action</span>) =&gt;</span> { <span class="hljs-keyword">switch</span> (action.type) { <span class="hljs-keyword">case</span> loginAction.SUCCESS: { <span class="hljs-keyword">const</span> { account, session } = action.payload; <span class="hljs-keyword">return</span> { ...state, account, session }; } <span class="hljs-keyword">case</span> logoutAction.TRIGGER: { <span class="hljs-keyword">const</span> { session } = action.payload; <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`LOGOUT Reducer Session - <span class="hljs-subst">${session}</span>`</span>); <span class="hljs-keyword">return</span> {}; } <span class="hljs-keyword">default</span>: <span class="hljs-keyword">return</span> state; } }; <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> reducer;</code></pre> <h5 id="combine-reducer">Combine Reducer</h5> <pre><code class="language-typescript"><span class="hljs-keyword">import</span> { combineReducers } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux'</span>; <span class="hljs-keyword">import</span> { all } <span class="hljs-keyword">from</span> <span class="hljs-string">'redux-saga/effects'</span>; <span class="hljs-keyword">import</span> auth, { authSaga } <span class="hljs-keyword">from</span> <span class="hljs-string">'./auth'</span>; <span class="hljs-keyword">const</span> reducers = combineReducers({ auth }); <span class="hljs-keyword">export</span> <span class="hljs-keyword">type</span> AppState = ReturnType&lt;<span class="hljs-keyword">typeof</span> reducers&gt;; <span class="hljs-comment">// saga</span> <span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> rootSaga = <span class="hljs-function"><span class="hljs-keyword">function</span>*(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">yield</span> all([authSaga()]); }; <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> reducers;</code></pre> <h5 id="container">Container</h5> <pre><code class="language-typescript">interface IState { account: string; loading: boolean; } type IProp = ReturnType&lt;typeof mapStateToProps&gt; &amp; typeof mapDispatchToProps; export class Dash extends PureComponent&lt;IProp, IState&gt; { state: IState = { account: '', loading: false }; handleLogin = async () =&gt; { const { loginAction } = this.props; const { account } = this.state; this.setState({ loading: true }); const { promise } = loginAction({ account }); const result = await promise; alert(`You are now logged in as ${result}`); this.setState({ loading: false }); }; handleLogout = async () =&gt; { const { session, logoutAction } = this.props; if (session) { logoutAction({ session }); } }; render() { const { session, account: authAccount } = this.props; const { account, loading } = this.state; const loggedIn = !!session; return ( &lt;div style={{ display: 'flex', height: 500, background: 'cyan', justifyContent: 'center', alignItems: 'center' }} &gt; &lt;div&gt; &lt;p&gt;Status: {loggedIn ? 'Logged In' : 'Logged Out'}&lt;/p&gt; &lt;p&gt;Session: {session}&lt;/p&gt; &lt;p&gt;Email: {authAccount}&lt;/p&gt; {loading ? ( '...loading' ) : loggedIn ? ( &lt;button onClick={this.handleLogout}&gt;Logout&lt;/button&gt; ) : ( &lt;&gt; &lt;p&gt; &lt;input type="text" placeholder="account" value={account} onChange={({ target: { value } }) =&gt; this.setState({ account: value }) } /&gt; &lt;/p&gt; &lt;button onClick={this.handleLogin}&gt;Login&lt;/button&gt; &lt;/&gt; )} &lt;/div&gt; &lt;/div&gt; ); } } const mapStateToProps = ({ auth: { account, session } }: AppState) =&gt; ({ account, session }); const mapDispatchToProps = { loginAction, logoutAction }; export default connect( mapStateToProps, mapDispatchToProps )(Dash);</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> <li class=" tsd-kind-external-module"> <a href="modules/_index_.html">"index"</a> </li> <li class=" tsd-kind-external-module"> <a href="modules/_index_test_.html">"index.test"</a> </li> <li class=" tsd-kind-external-module"> <a href="modules/_types_.html">"types"</a> </li> </ul> </nav> <nav class="tsd-navigation secondary menu-sticky"> <ul class="before-current"> </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> </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="http://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>