73 lines
2.2 KiB
Plaintext
73 lines
2.2 KiB
Plaintext
import { enqueueRender } from './component';
|
|
|
|
export let i = 0;
|
|
|
|
export function createContext(defaultValue, contextId) {
|
|
contextId = '__cC' + i++;
|
|
|
|
const context = {
|
|
_id: contextId,
|
|
_defaultValue: defaultValue,
|
|
/** @type {import('./internal').FunctionComponent} */
|
|
Consumer(props, contextValue) {
|
|
// return props.children(
|
|
// context[contextId] ? context[contextId].props.value : defaultValue
|
|
// );
|
|
return props.children(contextValue);
|
|
},
|
|
/** @type {import('./internal').FunctionComponent} */
|
|
Provider(props) {
|
|
if (!this.getChildContext) {
|
|
/** @type {import('./internal').Component[]} */
|
|
let subs = [];
|
|
let ctx = {};
|
|
ctx[contextId] = this;
|
|
|
|
this.getChildContext = () => ctx;
|
|
|
|
this.shouldComponentUpdate = function(_props) {
|
|
if (this.props.value !== _props.value) {
|
|
// I think the forced value propagation here was only needed when `options.debounceRendering` was being bypassed:
|
|
// https://github.com/preactjs/preact/commit/4d339fb803bea09e9f198abf38ca1bf8ea4b7771#diff-54682ce380935a717e41b8bfc54737f6R358
|
|
// In those cases though, even with the value corrected, we're double-rendering all nodes.
|
|
// It might be better to just tell folks not to use force-sync mode.
|
|
// Currently, using `useContext()` in a class component will overwrite its `this.context` value.
|
|
// subs.some(c => {
|
|
// c.context = _props.value;
|
|
// enqueueRender(c);
|
|
// });
|
|
|
|
// subs.some(c => {
|
|
// c.context[contextId] = _props.value;
|
|
// enqueueRender(c);
|
|
// });
|
|
subs.some(c => {
|
|
c._force = true;
|
|
enqueueRender(c);
|
|
});
|
|
}
|
|
};
|
|
|
|
this.sub = c => {
|
|
subs.push(c);
|
|
let old = c.componentWillUnmount;
|
|
c.componentWillUnmount = () => {
|
|
subs.splice(subs.indexOf(c), 1);
|
|
if (old) old.call(c);
|
|
};
|
|
};
|
|
}
|
|
|
|
return props.children;
|
|
}
|
|
};
|
|
|
|
// Devtools needs access to the context object when it
|
|
// encounters a Provider. This is necessary to support
|
|
// setting `displayName` on the context object instead
|
|
// of on the component itself. See:
|
|
// https://reactjs.org/docs/context.html#contextdisplayname
|
|
|
|
return (context.Provider._contextRef = context.Consumer.contextType = context);
|
|
}
|