redux-react-hook
Advanced tools
Comparing version 3.2.1 to 3.3.0
# Changelog for redux-react-hook | ||
## v3.3.0 | ||
Apr 5, 2019 | ||
- Simplify implementation, avoiding stale reads (thanks @Turanchoks!) | ||
- Remove `prop-type` as a `peerDependency` | ||
- Hand role TypeScript types to work around issues with create-react-app | ||
- Add Flow types to distributed build | ||
## v3.2.1 | ||
@@ -14,3 +23,3 @@ | ||
- Avoid double render if new mapState returns same mappedState (thanks @Turanchoks!) | ||
- Add create function for better typing (@thanks nmn!) | ||
- Add create function for better typing (thanks @nmn!) | ||
@@ -17,0 +26,0 @@ ## v3.1.0 |
/// <reference types="react" /> | ||
import { create } from './create'; | ||
export declare const StoreContext: import("react").Context<any>, useDispatch: () => import("redux").Dispatch<any>, useMappedState: <TResult>(mapState: (state: any) => TResult) => TResult; | ||
export { create }; | ||
/// <reference types="redux" /> | ||
import {Context} from 'react'; | ||
import {Action, Dispatch, Store} from 'redux'; | ||
/** | ||
* To use redux-react-hook with stronger type safety, or to use with multiple | ||
* stores in the same app, create() your own instance and re-export the returned | ||
* functions. | ||
*/ | ||
export declare function create< | ||
TState, | ||
TAction extends Action, | ||
TStore extends Store<TState, TAction> | ||
>(): { | ||
StoreContext: React.Context<TStore | null>; | ||
useMappedState: <TResult>(mapState: (state: TState) => TResult) => TResult; | ||
useDispatch: () => Dispatch<TAction>; | ||
}; | ||
export declare const StoreContext: Context<any>; | ||
export declare const useDispatch: () => Dispatch<any>; | ||
/** | ||
* Your passed in mapState function should be memoized with useCallback to avoid | ||
* resubscribing every render. If you don't use other props in mapState, pass | ||
* an empty array [] as the dependency list so the callback isn't recreated | ||
* every render. | ||
* | ||
* const todo = useMappedState(useCallback( | ||
* state => state.todos.get(id), | ||
* [id], | ||
* )); | ||
*/ | ||
export declare const useMappedState: <TResult>( | ||
mapState: (state: any) => TResult, | ||
) => TResult; |
@@ -1,3 +0,32 @@ | ||
import { createContext, useContext, useState, useRef, useEffect } from 'react'; | ||
import { createContext, useContext, useMemo, useReducer, useRef, useEffect } from 'react'; | ||
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. All rights reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use | ||
this file except in compliance with the License. You may obtain a copy of the | ||
License at http://www.apache.org/licenses/LICENSE-2.0 | ||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED | ||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, | ||
MERCHANTABLITY OR NON-INFRINGEMENT. | ||
See the Apache Version 2.0 License for specific language governing permissions | ||
and limitations under the License. | ||
***************************************************************************** */ | ||
/* global Reflect, Promise */ | ||
var extendStatics = function(d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
function __extends(d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
} | ||
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved | ||
@@ -39,4 +68,21 @@ // From https://github.com/reduxjs/react-redux/blob/3e53ff96ed10f71c21346f08823e503df724db35/src/utils/shallowEqual.js | ||
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved | ||
var CONTEXT_ERROR_MESSAGE = 'redux-react-hook requires your Redux store to ' + | ||
'be passed through context via the <StoreContext.Provider>'; | ||
var MissingProviderError = /** @class */ (function (_super) { | ||
__extends(MissingProviderError, _super); | ||
function MissingProviderError() { | ||
return _super.call(this, 'redux-react-hook requires your Redux store to be passed through ' + | ||
'context via the <StoreContext.Provider>') || this; | ||
} | ||
return MissingProviderError; | ||
}(Error)); | ||
function memoizeSingleArg(fn) { | ||
var value; | ||
var prevArg; | ||
return function (arg) { | ||
if (prevArg !== arg) { | ||
prevArg = arg; | ||
value = fn(arg); | ||
} | ||
return value; | ||
}; | ||
} | ||
/** | ||
@@ -63,27 +109,22 @@ * To use redux-react-hook with stronger type safety, or to use with multiple | ||
if (!store) { | ||
throw new Error(CONTEXT_ERROR_MESSAGE); | ||
throw new MissingProviderError(); | ||
} | ||
var runMapState = function () { return mapState(store.getState()); }; | ||
var _a = useState(runMapState), derivedState = _a[0], setDerivedState = _a[1]; | ||
var lastStore = useRef(store); | ||
var lastMapState = useRef(mapState); | ||
// Keep lastDerivedState in a ref and update it imperatively | ||
// after calling setDerivedState so it's always up-to-date. | ||
// We can't update it in useEffect because state might be updated | ||
// synchronously multiple times before render occurs. | ||
var lastDerivedState = useRef(derivedState); | ||
var wrappedSetDerivedState = function () { | ||
var newDerivedState = runMapState(); | ||
if (!shallowEqual(newDerivedState, lastDerivedState.current)) { | ||
setDerivedState(newDerivedState); | ||
lastDerivedState.current = newDerivedState; | ||
} | ||
}; | ||
// If the store or mapState change, rerun mapState | ||
if (lastStore.current !== store || lastMapState.current !== mapState) { | ||
lastStore.current = store; | ||
lastMapState.current = mapState; | ||
wrappedSetDerivedState(); | ||
} | ||
// We don't keep the derived state but call mapState on every render with current state. | ||
// This approach guarantees that useMappedState returns up-to-date derived state. | ||
// Since mapState can be expensive and must be a pure function of state we memoize it. | ||
var memoizedMapState = useMemo(function () { return memoizeSingleArg(mapState); }, [ | ||
mapState, | ||
]); | ||
var state = store.getState(); | ||
var derivedState = memoizedMapState(state); | ||
// Since we don't keep the derived state we still need to trigger | ||
// an update when derived state changes. | ||
var _a = useReducer(function (x) { return x + 1; }, 0), forceUpdate = _a[1]; | ||
// Keep previously commited derived state in a ref. Compare it to the new | ||
// one when an action is dispatched and call forceUpdate if they are different. | ||
var lastStateRef = useRef(derivedState); | ||
useEffect(function () { | ||
lastStateRef.current = derivedState; | ||
}); | ||
useEffect(function () { | ||
var didUnsubscribe = false; | ||
@@ -98,3 +139,7 @@ // Run the mapState callback and if the result has changed, make the | ||
} | ||
wrappedSetDerivedState(); | ||
var newDerivedState = memoizedMapState(store.getState()); | ||
if (!shallowEqual(newDerivedState, lastStateRef.current)) { | ||
// In TS definitions userReducer's dispatch requires an argument | ||
forceUpdate(); | ||
} | ||
}; | ||
@@ -112,3 +157,3 @@ // Pull data from the store after first render in case the store has | ||
}; | ||
}, [store, mapState]); | ||
}, [store, memoizedMapState]); | ||
return derivedState; | ||
@@ -119,3 +164,3 @@ } | ||
if (!store) { | ||
throw new Error(CONTEXT_ERROR_MESSAGE); | ||
throw new MissingProviderError(); | ||
} | ||
@@ -122,0 +167,0 @@ return store.dispatch; |
@@ -7,2 +7,31 @@ 'use strict'; | ||
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. All rights reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use | ||
this file except in compliance with the License. You may obtain a copy of the | ||
License at http://www.apache.org/licenses/LICENSE-2.0 | ||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED | ||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, | ||
MERCHANTABLITY OR NON-INFRINGEMENT. | ||
See the Apache Version 2.0 License for specific language governing permissions | ||
and limitations under the License. | ||
***************************************************************************** */ | ||
/* global Reflect, Promise */ | ||
var extendStatics = function(d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
function __extends(d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
} | ||
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved | ||
@@ -44,4 +73,21 @@ // From https://github.com/reduxjs/react-redux/blob/3e53ff96ed10f71c21346f08823e503df724db35/src/utils/shallowEqual.js | ||
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved | ||
var CONTEXT_ERROR_MESSAGE = 'redux-react-hook requires your Redux store to ' + | ||
'be passed through context via the <StoreContext.Provider>'; | ||
var MissingProviderError = /** @class */ (function (_super) { | ||
__extends(MissingProviderError, _super); | ||
function MissingProviderError() { | ||
return _super.call(this, 'redux-react-hook requires your Redux store to be passed through ' + | ||
'context via the <StoreContext.Provider>') || this; | ||
} | ||
return MissingProviderError; | ||
}(Error)); | ||
function memoizeSingleArg(fn) { | ||
var value; | ||
var prevArg; | ||
return function (arg) { | ||
if (prevArg !== arg) { | ||
prevArg = arg; | ||
value = fn(arg); | ||
} | ||
return value; | ||
}; | ||
} | ||
/** | ||
@@ -68,27 +114,22 @@ * To use redux-react-hook with stronger type safety, or to use with multiple | ||
if (!store) { | ||
throw new Error(CONTEXT_ERROR_MESSAGE); | ||
throw new MissingProviderError(); | ||
} | ||
var runMapState = function () { return mapState(store.getState()); }; | ||
var _a = react.useState(runMapState), derivedState = _a[0], setDerivedState = _a[1]; | ||
var lastStore = react.useRef(store); | ||
var lastMapState = react.useRef(mapState); | ||
// Keep lastDerivedState in a ref and update it imperatively | ||
// after calling setDerivedState so it's always up-to-date. | ||
// We can't update it in useEffect because state might be updated | ||
// synchronously multiple times before render occurs. | ||
var lastDerivedState = react.useRef(derivedState); | ||
var wrappedSetDerivedState = function () { | ||
var newDerivedState = runMapState(); | ||
if (!shallowEqual(newDerivedState, lastDerivedState.current)) { | ||
setDerivedState(newDerivedState); | ||
lastDerivedState.current = newDerivedState; | ||
} | ||
}; | ||
// If the store or mapState change, rerun mapState | ||
if (lastStore.current !== store || lastMapState.current !== mapState) { | ||
lastStore.current = store; | ||
lastMapState.current = mapState; | ||
wrappedSetDerivedState(); | ||
} | ||
// We don't keep the derived state but call mapState on every render with current state. | ||
// This approach guarantees that useMappedState returns up-to-date derived state. | ||
// Since mapState can be expensive and must be a pure function of state we memoize it. | ||
var memoizedMapState = react.useMemo(function () { return memoizeSingleArg(mapState); }, [ | ||
mapState, | ||
]); | ||
var state = store.getState(); | ||
var derivedState = memoizedMapState(state); | ||
// Since we don't keep the derived state we still need to trigger | ||
// an update when derived state changes. | ||
var _a = react.useReducer(function (x) { return x + 1; }, 0), forceUpdate = _a[1]; | ||
// Keep previously commited derived state in a ref. Compare it to the new | ||
// one when an action is dispatched and call forceUpdate if they are different. | ||
var lastStateRef = react.useRef(derivedState); | ||
react.useEffect(function () { | ||
lastStateRef.current = derivedState; | ||
}); | ||
react.useEffect(function () { | ||
var didUnsubscribe = false; | ||
@@ -103,3 +144,7 @@ // Run the mapState callback and if the result has changed, make the | ||
} | ||
wrappedSetDerivedState(); | ||
var newDerivedState = memoizedMapState(store.getState()); | ||
if (!shallowEqual(newDerivedState, lastStateRef.current)) { | ||
// In TS definitions userReducer's dispatch requires an argument | ||
forceUpdate(); | ||
} | ||
}; | ||
@@ -117,3 +162,3 @@ // Pull data from the store after first render in case the store has | ||
}; | ||
}, [store, mapState]); | ||
}, [store, memoizedMapState]); | ||
return derivedState; | ||
@@ -124,3 +169,3 @@ } | ||
if (!store) { | ||
throw new Error(CONTEXT_ERROR_MESSAGE); | ||
throw new MissingProviderError(); | ||
} | ||
@@ -127,0 +172,0 @@ return store.dispatch; |
{ | ||
"name": "redux-react-hook", | ||
"version": "3.2.1", | ||
"version": "3.3.0", | ||
"description": "React hook for accessing a Redux store.", | ||
@@ -31,3 +31,2 @@ "author": { | ||
"peerDependencies": { | ||
"prop-types": "^15.5.4", | ||
"react": "^16.8.1", | ||
@@ -46,4 +45,4 @@ "redux": "^4.0.1" | ||
"prettier": "^1.16.4", | ||
"react": "^16.8.1", | ||
"react-dom": "^16.8.1", | ||
"react": "^16.8.3", | ||
"react-dom": "^16.8.3", | ||
"react-scripts": "^2.1.3", | ||
@@ -50,0 +49,0 @@ "redux": "^4.0.1", |
@@ -5,5 +5,6 @@ # redux-react-hook | ||
[](https://travis-ci.com/facebookincubator/redux-react-hook) | ||
[](https://travis-ci.com/facebookincubator/redux-react-hook) | ||
[](https://www.npmjs.com/package/redux-react-hook) | ||
[](https://bundlephobia.com/result?p=redux-react-hook@latest) | ||
[](https://bundlephobia.com/result?p=redux-react-hook@latest) | ||
[](https://www.npmjs.com/package/redux-react-hook) | ||
@@ -10,0 +11,0 @@ ## Table of Contents |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
66389
2
373
250
10
1