Skip to content

Commit

Permalink
A temporal workaround with useLayoutEffect in DEV (dai-shi/use-contex…
Browse files Browse the repository at this point in the history
  • Loading branch information
dai-shi committed Feb 24, 2020
1 parent 001927d commit 1bc3c6f
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Change Log

## [Unreleased]
### Changed
- A workaround for React render warning (hopefully temporarily)

## [4.5.0] - 2020-02-03
### Changed
Expand Down
33 changes: 25 additions & 8 deletions dist/Provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,29 @@ var Provider = function Provider(_ref) {
forceUpdate = _useReducer2[1];

var state = store.getState();
var listeners = (0, _react.useRef)([]); // we call listeners in render intentionally.
// listeners are not technically pure, but
// otherwise we can't get benefits from concurrent mode.
// we make sure to work with double or more invocation of listeners.

listeners.current.forEach(function (listener) {
return listener(state);
});
var listeners = (0, _react.useRef)([]);

if (process.env.NODE_ENV !== 'production') {
// we use layout effect to eliminate warnings.
// but, this leads tearing with startTransition.
// https://github.com/dai-shi/use-context-selector/pull/13
// eslint-disable-next-line react-hooks/rules-of-hooks
(0, _react.useLayoutEffect)(function () {
listeners.current.forEach(function (listener) {
return listener(state);
});
});
} else {
// we call listeners in render for optimization.
// although this is not a recommended pattern,
// so far this is only the way to make it as expected.
// we are looking for better solutions.
// https://github.com/dai-shi/use-context-selector/pull/12
listeners.current.forEach(function (listener) {
return listener(state);
});
}

var subscribe = (0, _react.useCallback)(function (listener) {
listeners.current.push(listener);

Expand All @@ -87,6 +102,8 @@ var Provider = function Provider(_ref) {
var unsubscribe = store.subscribe(function () {
forceUpdate();
});
forceUpdate(); // in case it's already changed

return unsubscribe;
}, [store]);
return (0, _react.createElement)(customContext.Provider, {
Expand Down
23 changes: 18 additions & 5 deletions src/Provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
createContext,
createElement,
useCallback,
useLayoutEffect,
useEffect,
useRef,
useReducer,
Expand Down Expand Up @@ -46,11 +47,22 @@ export const Provider = ({
const [, forceUpdate] = useReducer((c) => c + 1, 0);
const state = store.getState();
const listeners = useRef([]);
// we call listeners in render intentionally.
// listeners are not technically pure, but
// otherwise we can't get benefits from concurrent mode.
// we make sure to work with double or more invocation of listeners.
listeners.current.forEach((listener) => listener(state));
if (process.env.NODE_ENV !== 'production') {
// we use layout effect to eliminate warnings.
// but, this leads tearing with startTransition.
// https://github.com/dai-shi/use-context-selector/pull/13
// eslint-disable-next-line react-hooks/rules-of-hooks
useLayoutEffect(() => {
listeners.current.forEach((listener) => listener(state));
});
} else {
// we call listeners in render for optimization.
// although this is not a recommended pattern,
// so far this is only the way to make it as expected.
// we are looking for better solutions.
// https://github.com/dai-shi/use-context-selector/pull/12
listeners.current.forEach((listener) => listener(state));
}
const subscribe = useCallback((listener) => {
listeners.current.push(listener);
const unsubscribe = () => {
Expand All @@ -65,6 +77,7 @@ export const Provider = ({
const unsubscribe = store.subscribe(() => {
forceUpdate();
});
forceUpdate(); // in case it's already changed
return unsubscribe;
}, [store]);
return createElement(
Expand Down

0 comments on commit 1bc3c6f

Please sign in to comment.