Upgrade from 3.x to 4.0.0
This release introduces changes to error handling.
Previously, the parameter of the rejected promise callback was both the dispatched action and an error object. The middleware also always constructed a new error object, which caused unexpected mutation and circular references.
Now, the parameter of the rejected promise callback is the value of reject. The middleware does not construct a new error; it is your responsibility to make sure the promise is rejected with an Error object.
1
// before
2
const bar = () => ({
3
type: 'FOO',
4
payload: new Promise(() => {
5
reject('foo');
6
})
7
});.then(() => null, ({ reason, action }) => {
8
console.log(action.type): // => 'FOO'
9
console.log(reason.message); // => 'foo'
10
});
11
​
12
// after
13
const bar = () => ({
14
type: 'FOO',
15
payload: new Promise(() => {
16
​
17
/**
18
* Make sure the promise is rejected with an error. You
19
* can also use `reject(new Error('foo'));`. It's a best
20
* practice to reject a promise with an Error object.
21
*/
22
throw new Error('foo');
23
})
24
});.then(() => null, error => {
25
console.log(error instanceof Error); // => true
26
console.log(error.message); // => 'foo'
27
});
Copied!

2.x to 3.0.0

This release introduces some major changes to the functionality of the middleware:
First, the middleware returns a promise instead of the action.
1
// before
2
const foo = () => ({
3
type: 'FOO',
4
payload: {
5
promise: Promise.resolve('foo')
6
}
7
});
8
​
9
foo().action.promise.then(value => {
10
console.log(value); // => 'foo'
11
});
12
​
13
// after
14
const bar = () => ({
15
type: 'BAR',
16
payload: Promise.resolve('bar')
17
});
18
​
19
bar().then(({ value }) => {
20
console.log(value); // => 'bar'
21
});
Copied!
Second, a new promise is created so .then() and .catch() work as expected.
1
// before
2
const foo = () => ({
3
type: 'FOO',
4
payload: {
5
promise: Promise.reject('foo')
6
}
7
});
8
​
9
foo().action.promise.then(
10
value => {
11
console.log(value); // => 'foo'
12
},
13
reason => {
14
// nothing happens
15
}
16
);
17
​
18
// after
19
const bar = () => ({
20
type: 'BAR',
21
payload: Promise.reject('bar')
22
});
23
​
24
bar().then(
25
({ value }) => {
26
// ...
27
},
28
({ reason }) => {
29
console.log(reason); // => 'bar'
30
}
31
);
32
​
33
const baz = () => ({
34
type: 'BAZ',
35
payload: new Promise((resolve, reject) => {
36
throw 'baz'
37
})
38
});
39
​
40
bar().catch(({ reason }) => {
41
console.log(reason) // => 'baz'
42
});
Copied!
Third, promises can be explicitly or implicitly in the action object.
1
// before
2
const foo = () => ({
3
type: 'FOO',
4
payload: {
5
promise: Promise.resolve()
6
}
7
});
8
​
9
// after, with implicit promise as the value of the 'payload' property
10
const bar = () => ({
11
type: 'BAR',
12
payload: Promise.resolve()
13
});
Copied!
Of course, if you prefer the explicit syntax, this still works. This syntax is also required for optimistic updates.
1
// after, but with explicit 'promise' property and 'data' property
2
const bar = () => ({
3
type: 'BAZ',
4
payload: {
5
promise: Promise.resolve(),
6
data: ...
7
}
8
});
Copied!
Fourth, thunks are no longer bound to the promise. If you are chaining actions with Redux Thunk, this is critical change.
1
// before, with Redux Thunk
2
const foo = () => ({
3
type: 'FOO',
4
payload: {
5
promise: new Promise((resolve, reject) => {
6
...
7
}).then(
8
value => (action, dispatch) => {
9
// handle fulfilled
10
dispatch(someSuccessHandlerActionCreator());
11
},
12
reason => (action, dispatch) => {
13
// handle rejected
14
dispatch(someErrorHandlerActionCreator());
15
}
16
)
17
}
18
});
19
​
20
// after, with Redux Thunk
21
const bar = () => {
22
return (dispatch, getState) => {
23
​
24
return dispatch({
25
type: 'FOO',
26
payload: Promise.resolve('foo')
27
}).then(
28
({ value, action }) => {
29
console.log(value); // => 'foo'
30
console.log(action.type); // => 'FOO_FULFILLED'
31
dispatch(someSuccessHandlerActionCreator());
32
},
33
({ reason, action }) => {
34
// handle rejected
35
dispatch(someErrorHandlerActionCreator());
36
}
37
);
38
};
39
};
Copied!
Last modified 3yr ago
Copy link
Contents
2.x to 3.0.0