redux-actions-promise-wrapper
Version:
Type safe wrapper for redux actions (compatible with redux-saga)
363 lines (339 loc) • 17.8 kB
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>)<
{
email: <span class="hljs-built_in">string</span>;
password: <span class="hljs-built_in">string</span>;
},
{
session: <span class="hljs-built_in">string</span>;
}
>();</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>)<{
session: <span class="hljs-built_in">string</span>;
}>();
<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<{
loginAction: <span class="hljs-keyword">typeof</span> loginAction;
logoutAction: <span class="hljs-keyword">typeof</span> logoutAction;
}>;
<span class="hljs-keyword">const</span> reducer: Reducer<IAuth, Actions> = <span class="hljs-function">(<span class="hljs-params">state = INITIAL_STATE, action</span>) =></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<<span class="hljs-keyword">typeof</span> reducers>;
<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<typeof mapStateToProps> & typeof mapDispatchToProps;
export class Dash extends PureComponent<IProp, IState> {
state: IState = {
account: '',
loading: false
};
handleLogin = async () => {
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 () => {
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 (
<div
style={{
display: 'flex',
height: 500,
background: 'cyan',
justifyContent: 'center',
alignItems: 'center'
}}
>
<div>
<p>Status: {loggedIn ? 'Logged In' : 'Logged Out'}</p>
<p>Session: {session}</p>
<p>Email: {authAccount}</p>
{loading ? (
'...loading'
) : loggedIn ? (
<button onClick={this.handleLogout}>Logout</button>
) : (
<>
<p>
<input
type="text"
placeholder="account"
value={account}
onChange={({ target: { value } }) =>
this.setState({ account: value })
}
/>
</p>
<button onClick={this.handleLogin}>Login</button>
</>
)}
</div>
</div>
);
}
}
const mapStateToProps = ({ auth: { account, session } }: AppState) => ({
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>