From 653491baad1645333c92c8361da4a9ba5a87995d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B8=E5=BE=92=E6=AD=A3=E7=BE=8E?= <1669866773@qq.com> Date: Fri, 8 Jun 2018 11:43:08 +0800 Subject: [PATCH 1/3] Update implementation.js Provider and Consumer share an internal inaccessible emitter, no more getChildContext or contextTypes --- src/implementation.js | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/implementation.js b/src/implementation.js index e00756f..624b22e 100644 --- a/src/implementation.js +++ b/src/implementation.js @@ -48,7 +48,10 @@ function createEventEmitter(value) { }, off(handler) { - handlers = handlers.filter(h => h !== handler); + let index = handlers.indexOf(handler) ;//only remove matched handler + if(i !== -1){ + handlers.splice(i, 1); + } }, get() { @@ -70,20 +73,13 @@ function createReactContext( defaultValue: T, calculateChangedBits: ?(a: T, b: T) => number ): Context { - const contextProp = '__create-react-context-' + gud() + '__'; - + let emitter; // Provider and Consumer share an internal inaccessible emitter, no more getChildContext or contextTypes class Provider extends Component> { - emitter = createEventEmitter(this.props.value); - - static childContextTypes = { - [contextProp]: PropTypes.object.isRequired - }; - - getChildContext() { - return { - [contextProp]: this.emitter - }; + constructor(props, context){ + super(props, context); + emitter = createEventEmitter(props.value); } + componentWillReceiveProps(nextProps) { if (this.props.value !== nextProps.value) { @@ -110,7 +106,7 @@ function createReactContext( changedBits |= 0; if (changedBits !== 0) { - this.emitter.set(nextProps.value, changedBits); + emitter.set(nextProps.value, changedBits);//Notify all consumers to update } } } @@ -122,9 +118,6 @@ function createReactContext( } class Consumer extends Component, ConsumerState> { - static contextTypes = { - [contextProp]: PropTypes.object - }; observedBits: number; @@ -141,8 +134,8 @@ function createReactContext( } componentDidMount() { - if (this.context[contextProp]) { - this.context[contextProp].on(this.onUpdate); + if (emitter) { + emitter.on(this.onUpdate); } let { observedBits } = this.props; this.observedBits = @@ -152,14 +145,14 @@ function createReactContext( } componentWillUnmount() { - if (this.context[contextProp]) { - this.context[contextProp].off(this.onUpdate); + if (emitter) { + emitter.off(this.onUpdate); } } getValue(): T { - if (this.context[contextProp]) { - return this.context[contextProp].get(); + if (emitter) { + return emitter.get(); } else { return defaultValue; } From ee784221ba4174e2864cc56f5bb1f6345e0c3d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B8=E5=BE=92=E6=AD=A3=E7=BE=8E?= <1669866773@qq.com> Date: Fri, 8 Jun 2018 21:51:46 +0800 Subject: [PATCH 2/3] Update implementation.js Protect the emitter --- src/implementation.js | 44 ++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/implementation.js b/src/implementation.js index 624b22e..e4199f9 100644 --- a/src/implementation.js +++ b/src/implementation.js @@ -48,10 +48,7 @@ function createEventEmitter(value) { }, off(handler) { - let index = handlers.indexOf(handler) ;//only remove matched handler - if(i !== -1){ - handlers.splice(i, 1); - } + handlers = handlers.filter(h => h !== handler); }, get() { @@ -73,14 +70,21 @@ function createReactContext( defaultValue: T, calculateChangedBits: ?(a: T, b: T) => number ): Context { - let emitter; // Provider and Consumer share an internal inaccessible emitter, no more getChildContext or contextTypes + let emitter; // Provider and Consumer share an internal inaccessible emitter class Provider extends Component> { + static childContextTypes = { + [contextProp]: PropTypes.string.isRequired + }; constructor(props, context){ super(props, context); emitter = createEventEmitter(props.value); } - - + + getChildContext() { + return { + [contextProp]: contextProp + } + } componentWillReceiveProps(nextProps) { if (this.props.value !== nextProps.value) { let oldValue = this.props.value; @@ -106,7 +110,7 @@ function createReactContext( changedBits |= 0; if (changedBits !== 0) { - emitter.set(nextProps.value, changedBits);//Notify all consumers to update + emitter.set(nextProps.value, changedBits);//Notify all consumers to update } } } @@ -118,13 +122,15 @@ function createReactContext( } class Consumer extends Component, ConsumerState> { + static contextTypes = { + [contextProp]: PropTypes.string + }; observedBits: number; - state: ConsumerState = { value: this.getValue() }; - + componentWillReceiveProps(nextProps) { let { observedBits } = nextProps; this.observedBits = @@ -134,7 +140,7 @@ function createReactContext( } componentDidMount() { - if (emitter) { + if (this.context[contextProp]) { emitter.on(this.onUpdate); } let { observedBits } = this.props; @@ -145,17 +151,17 @@ function createReactContext( } componentWillUnmount() { - if (emitter) { - emitter.off(this.onUpdate); - } + if (this.context[contextProp]) { + emitter.off(this.onUpdate); + } } getValue(): T { - if (emitter) { - return emitter.get(); - } else { - return defaultValue; - } + if (this.context[contextProp]) { + return emitter.get(); + } else { + return defaultValue; + } } onUpdate = (newValue, changedBits: number) => { From 026f57ad4a202f950c87947fb2c2ffd7da0b99a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B8=E5=BE=92=E6=AD=A3=E7=BE=8E?= <1669866773@qq.com> Date: Sat, 9 Jun 2018 11:17:05 +0800 Subject: [PATCH 3/3] Update implementation.js add --- src/implementation.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/implementation.js b/src/implementation.js index e4199f9..84f464f 100644 --- a/src/implementation.js +++ b/src/implementation.js @@ -71,6 +71,8 @@ function createReactContext( calculateChangedBits: ?(a: T, b: T) => number ): Context { let emitter; // Provider and Consumer share an internal inaccessible emitter + const contextProp = '__create-react-context-' + gud() + '__'; + class Provider extends Component> { static childContextTypes = { [contextProp]: PropTypes.string.isRequired