1 | import { enqueueRender } from './component';
|
2 |
|
3 | export let i = 0;
|
4 |
|
5 | export function createContext(defaultValue, contextId) {
|
6 | contextId = '__cC' + i++;
|
7 |
|
8 | const context = {
|
9 | _id: contextId,
|
10 | _defaultValue: defaultValue,
|
11 | Consumer(props, contextValue) {
|
12 | // return props.children(
|
13 | // context[contextId] ? context[contextId].props.value : defaultValue
|
14 | // );
|
15 | return props.children(contextValue);
|
16 | },
|
17 | Provider(props, subs, ctx) {
|
18 | if (!this.getChildContext) {
|
19 | subs = [];
|
20 | ctx = {};
|
21 | ctx[contextId] = this;
|
22 |
|
23 | this.getChildContext = () => ctx;
|
24 |
|
25 | this.shouldComponentUpdate = function(_props) {
|
26 | if (this.props.value !== _props.value) {
|
27 | // I think the forced value propagation here was only needed when `options.debounceRendering` was being bypassed:
|
28 | // https://github.com/preactjs/preact/commit/4d339fb803bea09e9f198abf38ca1bf8ea4b7771#diff-54682ce380935a717e41b8bfc54737f6R358
|
29 | // In those cases though, even with the value corrected, we're double-rendering all nodes.
|
30 | // It might be better to just tell folks not to use force-sync mode.
|
31 | // Currently, using `useContext()` in a class component will overwrite its `this.context` value.
|
32 | // subs.some(c => {
|
33 | // c.context = _props.value;
|
34 | // enqueueRender(c);
|
35 | // });
|
36 |
|
37 | // subs.some(c => {
|
38 | // c.context[contextId] = _props.value;
|
39 | // enqueueRender(c);
|
40 | // });
|
41 | subs.some(enqueueRender);
|
42 | }
|
43 | };
|
44 |
|
45 | this.sub = c => {
|
46 | subs.push(c);
|
47 | let old = c.componentWillUnmount;
|
48 | c.componentWillUnmount = () => {
|
49 | subs.splice(subs.indexOf(c), 1);
|
50 | if (old) old.call(c);
|
51 | };
|
52 | };
|
53 | }
|
54 |
|
55 | return props.children;
|
56 | }
|
57 | };
|
58 |
|
59 | // Devtools needs access to the context object when it
|
60 | // encounters a Provider. This is necessary to support
|
61 | // setting `displayName` on the context object instead
|
62 | // of on the component itself. See:
|
63 | // https://reactjs.org/docs/context.html#contextdisplayname
|
64 |
|
65 | return (context.Provider._contextRef = context.Consumer.contextType = context);
|
66 | }
|