Skip to content

Commit 76a8758

Browse files
committed
do not notify children in render
1 parent f3e1d9f commit 76a8758

File tree

3 files changed

+29
-55
lines changed

3 files changed

+29
-55
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Change Log
22

33
## [Unreleased]
4+
### Changed
5+
- Notify child components updates in callback and effect not in render
46

57
## [4.7.0] - 2020-03-01
68
### Changed

dist/Provider.js

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ exports.Provider = exports.defaultContext = exports.createCustomContext = void 0
77

88
var _react = require("react");
99

10-
var _utils = require("./utils");
11-
1210
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
1311

1412
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
@@ -58,36 +56,17 @@ var Provider = function Provider(_ref) {
5856
customContext = _ref$customContext === void 0 ? defaultContext : _ref$customContext,
5957
children = _ref.children;
6058

61-
var _useReducer = (0, _react.useReducer)(function (c) {
62-
return c + 1;
63-
}, 0),
64-
_useReducer2 = _slicedToArray(_useReducer, 2),
65-
forceUpdate = _useReducer2[1];
59+
var _useState = (0, _react.useState)(store.getState()),
60+
_useState2 = _slicedToArray(_useState, 2),
61+
state = _useState2[0],
62+
setState = _useState2[1];
6663

67-
var state = store.getState();
6864
var listeners = (0, _react.useRef)([]);
69-
70-
if (process.env.NODE_ENV !== 'production') {
71-
// we use layout effect to eliminate warnings.
72-
// but, this leads tearing with startTransition.
73-
// https://github.com/dai-shi/use-context-selector/pull/13
74-
// eslint-disable-next-line react-hooks/rules-of-hooks
75-
(0, _utils.useIsomorphicLayoutEffect)(function () {
76-
listeners.current.forEach(function (listener) {
77-
return listener(state);
78-
});
79-
});
80-
} else {
81-
// we call listeners in render for optimization.
82-
// although this is not a recommended pattern,
83-
// so far this is only the way to make it as expected.
84-
// we are looking for better solutions.
85-
// https://github.com/dai-shi/use-context-selector/pull/12
65+
(0, _react.useEffect)(function () {
8666
listeners.current.forEach(function (listener) {
8767
return listener(state);
8868
});
89-
}
90-
69+
}, [state]);
9170
var subscribe = (0, _react.useCallback)(function (listener) {
9271
listeners.current.push(listener);
9372

@@ -101,10 +80,16 @@ var Provider = function Provider(_ref) {
10180
return unsubscribe;
10281
}, [store]);
10382
(0, _react.useEffect)(function () {
104-
var unsubscribe = store.subscribe(function () {
105-
forceUpdate();
106-
});
107-
forceUpdate(); // in case it's already changed
83+
var callback = function callback() {
84+
var nextState = store.getState();
85+
listeners.current.forEach(function (listener) {
86+
return listener(nextState);
87+
});
88+
setState(nextState);
89+
};
90+
91+
var unsubscribe = store.subscribe(callback);
92+
callback(); // in case it's already changed
10893

10994
return unsubscribe;
11095
}, [store]);

src/Provider.js

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@ import {
44
useCallback,
55
useEffect,
66
useRef,
7-
useReducer,
7+
useState,
88
} from 'react';
99

10-
import { useIsomorphicLayoutEffect } from './utils';
11-
1210
// -------------------------------------------------------
1311
// context
1412
// -------------------------------------------------------
@@ -45,25 +43,11 @@ export const Provider = ({
4543
customContext = defaultContext,
4644
children,
4745
}) => {
48-
const [, forceUpdate] = useReducer((c) => c + 1, 0);
49-
const state = store.getState();
46+
const [state, setState] = useState(store.getState());
5047
const listeners = useRef([]);
51-
if (process.env.NODE_ENV !== 'production') {
52-
// we use layout effect to eliminate warnings.
53-
// but, this leads tearing with startTransition.
54-
// https://github.com/dai-shi/use-context-selector/pull/13
55-
// eslint-disable-next-line react-hooks/rules-of-hooks
56-
useIsomorphicLayoutEffect(() => {
57-
listeners.current.forEach((listener) => listener(state));
58-
});
59-
} else {
60-
// we call listeners in render for optimization.
61-
// although this is not a recommended pattern,
62-
// so far this is only the way to make it as expected.
63-
// we are looking for better solutions.
64-
// https://github.com/dai-shi/use-context-selector/pull/12
48+
useEffect(() => {
6549
listeners.current.forEach((listener) => listener(state));
66-
}
50+
}, [state]);
6751
const subscribe = useCallback((listener) => {
6852
listeners.current.push(listener);
6953
const unsubscribe = () => {
@@ -75,10 +59,13 @@ export const Provider = ({
7559
return unsubscribe;
7660
}, [store]);
7761
useEffect(() => {
78-
const unsubscribe = store.subscribe(() => {
79-
forceUpdate();
80-
});
81-
forceUpdate(); // in case it's already changed
62+
const callback = () => {
63+
const nextState = store.getState();
64+
listeners.current.forEach((listener) => listener(nextState));
65+
setState(nextState);
66+
};
67+
const unsubscribe = store.subscribe(callback);
68+
callback(); // in case it's already changed
8269
return unsubscribe;
8370
}, [store]);
8471
return createElement(

0 commit comments

Comments
 (0)