Skip to content

Commit

Permalink
Release Version 6 (#231)
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Burtchaell committed Feb 3, 2019
1 parent 0b61389 commit 612043c
Show file tree
Hide file tree
Showing 23 changed files with 9,834 additions and 8,759 deletions.
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -40,17 +40,21 @@ const firstAction = () => {
- [Guides](/docs/guides/)
- [Examples](/examples)

**Heads Up:** Version 6 includes some breaking changes. Check the [upgrading guide](docs/upgrading/v6.md) for help.

## Issues
For bug reports and feature requests, [file an issue on GitHub](https://github.com/pburtchaell/redux-promise-middleware/issues/new).

For help, [ask a question on StackOverflow](https://stackoverflow.com/questions/tagged/redux-promise-middleware).

## Releases
- [Release History](https://github.com/pburtchaell/redux-promise-middleware/releases)
- [Upgrade from 5.x to 6.0.0](docs/upgrading/v6.md)
- [Upgrade from 4.x to 5.0.0](docs/upgrading/v5.md)
- [Upgrade from 3.x to 4.0.0](docs/upgrading/v4.md)

For older versions:
- [5.x](https://github.com/pburtchaell/redux-promise-middleware/tree/5.0.1)
- [4.x](https://github.com/pburtchaell/redux-promise-middleware/tree/4.4.0)
- [3.x](https://github.com/pburtchaell/redux-promise-middleware/tree/3.3.0)
- [2.x](https://github.com/pburtchaell/redux-promise-middleware/tree/2.4.0)
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Expand Up @@ -18,6 +18,7 @@
- [Use with Promises Resolved with Null Values](guides/null-values.md)

## Upgrade Guides
- [Upgrade from 5.x to 6.0.0](upgrading/v6.md)
- [Upgrade from 4.x to 5.0.0](upgrading/v5.md)
- [Upgrade from 3.x to 4.0.0](upgrading/v4.md)
- [Release History](https://github.com/pburtchaell/redux-promise-middleware/releases)
4 changes: 3 additions & 1 deletion docs/guides/custom-delimiters.md
Expand Up @@ -13,8 +13,10 @@ For example, given `FOO` async action, `PENDING` type will be appended with a un
To change the default, supply an optional configuration object to the middleware with the `promiseTypeDelimiter` property. This property accepts a new string to use as the delimiter.

```js
import { createPromise } from 'redux-promise-middleware';

applyMiddleware(
promiseMiddleware({
createPromise({
promiseTypeDelimiter: '/'
})
)
Expand Down
4 changes: 3 additions & 1 deletion docs/guides/custom-suffixes.md
Expand Up @@ -5,8 +5,10 @@ In the case you need to use different type suffixes, you can configure this glob
To change suffixes, you can supply an optional configuration object to the middleware. This object accepts an array of suffix strings that can be used instead of the default with a key of `promiseTypeSuffixes`.

```js
import { createPromise } from 'redux-promise-middleware';

applyMiddleware(
promiseMiddleware({
createPromise({
promiseTypeSuffixes: ['LOADING', 'SUCCESS', 'ERROR']
})
)
Expand Down
14 changes: 11 additions & 3 deletions docs/guides/reducers.md
Expand Up @@ -34,12 +34,20 @@ const fooReducer = (state = {}, action) => {
}
```

### Promise Suffixes
### Action Types

Optionally, the default promise suffixes can be imported from this module. This can be useful in your reducers.
Optionally, the default promise suffixes can be imported from this module.

```js
import { PENDING, FULFILLED, REJECTED } from 'redux-promise-middleware';
import { ActionType } from 'redux-promise-middleware';
```

This can be useful in your reducers to ensure types are more robust.

```js
const FOO_PENDING = `FOO_${ActionTypes.Pending}`;
const FOO_FULFILLED = `FOO_${ActionTypes.Fulfilled}`;
const FOO_REJECTED = `FOO_${ActionTypes.Rejected}`;
```

## Large Applications
Expand Down
11 changes: 6 additions & 5 deletions docs/introduction.md
Expand Up @@ -4,19 +4,20 @@

First, install the middleware.

npm: `npm i redux-promise-middleware -S`
yarn: `yarn add redux-promise-middleware`
```
npm i redux-promise-middleware -s
```

## Setup

Import the middleware and include it in `applyMiddleware` when creating the Redux store:

```js
import promiseMiddleware from 'redux-promise-middleware';
import promise from 'redux-promise-middleware'

composeStoreWithMiddleware = applyMiddleware(
promiseMiddleware()
)(createStore);
promise,
)(createStore)
```

## Use
Expand Down
120 changes: 120 additions & 0 deletions docs/upgrading/v6.md
@@ -0,0 +1,120 @@
# Upgrade from 5.x to 6.0.0

This version includes changes to the public API, making it easier to import and use the middleware.

## New: Preconfigured by Default

### Before

Previously, the middleware need to be instantiated with an optional configuration.

```js
import promiseMiddleware from 'redux-promise-middleware'

applyMiddleware(
promiseMiddleware({
// Optional configuration
}),
)(createStore)
```

This implementation enabled custom configuration, but, for most implementations, it is uncessary overhead.

### After

Now, the default export is preconfigured and ready to go.

```js
import promise from 'redux-promise-middleware'

applyMiddleware(
promise,
)(createStore)
```

The middleware still supports custom configuration: import `createPromise` and pass in the configuration object.

```js
import { createPromise } from 'redux-promise-middleware'

applyMiddleware(
createPromise({
// Custom configuration
typeDelimiter: '/',
}),
)(createStore)
```

## New: `ActionType` Export

### Before


```js
import { PENDING, FULFILLED, REJECTED } from 'redux-promise-middleware'
```

Previously, the middleware exported three string constants. One each for the pending, fulfilled and rejected action types. This is useful for reducers, for example:

```js
const reducer = (state = {}, action) => {
switch(action.type) {
case `FOO_${PENDING}`:
// ..

case `FOO_${FULFILLED}`:
// ...

default: return state;
}
}
```

This is a nice affordance, it could be better design if the action types were exported as an enum (E.g., an object, since this is just JavaScript), as opposed three individual strings.

### After

```js
import { ActionType } from 'redux-promise-middleware'
```

Now, the action types are exported as one enum.

```js
const reducer = (state = {}, action) => {
switch(action.type) {
case `FOO_${ActionTypes.Pending}`:
// ..

case `FOO_${ActionTypes.Fulfilled}`:
// ...

case `FOO_${ActionTypes.Rejected}`:
// ...

default: return state;
}
}
```

Using action types is entirely optional. One one hand, code benefits from more robust types and is less prone to static errors, but, on another hand, you and your team spends more time and effort writing the code.

At the end of the day, you can also just use regular strings like any other action.


```js
const reducer = (state = {}, action) => {
switch(action.type) {
case `FOO_PENDING`:
// ..

case `FOO_FULFILLED`:
// ...

case `FOO_REJECTED`:
// ...

default: return state;
}
}
```
3 changes: 3 additions & 0 deletions examples/using-typescript/.gitignore
@@ -0,0 +1,3 @@
.cache
dist
node_modules
11 changes: 11 additions & 0 deletions examples/using-typescript/README.md
@@ -0,0 +1,11 @@
# Using Promise Middleware with TypeScript

This example demonstrates how to use the middleware with TypeScript.

## Getting Started

- Clone this repository to your computer
- Open the folder for this example
- Run `npm i` to install dependencies
- Run `npm start` to start the example
- Open `http://localhost:1234` in a web browser
10 changes: 10 additions & 0 deletions examples/using-typescript/index.html
@@ -0,0 +1,10 @@
<!doctype html public>
<body>
<style>button { margin: 5px 0 10px 0; } img { max-width: 200px; }</style>
<title>Using Redux Promise Middleware</title>
<h1>Using Redux Promise Middleware</h1>
<p>This example demonstrates how to use the middleware to fetch data a JSON API.</p>
<hr />
<button id="load">Get Post</button>
<div id="mount"/>
<script async src="./index.ts"></script>
41 changes: 41 additions & 0 deletions examples/using-typescript/index.ts
@@ -0,0 +1,41 @@
import { AsyncAction } from 'redux-promise-middleware';
import store, { State } from './store';

/**
* @private
* Fetch an image of a dog from the [Dog API](https://dog.ceo/dog-api/)
*/
const getDog = (): AsyncAction => ({
type: 'GET_DOG',
payload: fetch('https://dog.ceo/api/breeds/image/random')
.then(response => response.json()),
});

/**
* @private
* Renders the given state to the given HTML DOM node
*/
const render = (mount: HTMLElement | null, state: State) => {
if (mount && state.isPending) {
mount.innerHTML = 'Loading...';
} else if (mount && state.image) {
mount.innerHTML = `<img src=${state.image} />`;
}
};

/**
* @private
* Renders the initial state of the example
*/
const initialize = () => {
const mount: HTMLElement | null = document.querySelector('#mount');

// Load the post when button is clicked
const button: HTMLElement | null = document.querySelector('#load');
if (button) button.addEventListener('click', () => store.dispatch(getDog()));

render(mount, store.getState());
store.subscribe(() => render(mount, store.getState()));
};

initialize();

0 comments on commit 612043c

Please sign in to comment.