From cea22e0ec7c474d81380d0bb56061ff04ebdfe88 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Thu, 9 Feb 2023 12:04:29 +0100 Subject: [PATCH] Fix createContext update being blocked by sCU --- src/create-context.js | 6 +++- test/browser/createContext.test.js | 44 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/create-context.js b/src/create-context.js index 750517dcf4..df939ee325 100644 --- a/src/create-context.js +++ b/src/create-context.js @@ -18,6 +18,7 @@ export function createContext(defaultValue, contextId) { /** @type {import('./internal').FunctionComponent} */ Provider(props) { if (!this.getChildContext) { + /** @type {import('./internal').Component[]} */ let subs = []; let ctx = {}; ctx[contextId] = this; @@ -40,7 +41,10 @@ export function createContext(defaultValue, contextId) { // c.context[contextId] = _props.value; // enqueueRender(c); // }); - subs.some(enqueueRender); + subs.some(c => { + c._force = true; + enqueueRender(c); + }); } }; diff --git a/test/browser/createContext.test.js b/test/browser/createContext.test.js index 092a2bad9b..611083db28 100644 --- a/test/browser/createContext.test.js +++ b/test/browser/createContext.test.js @@ -928,4 +928,48 @@ describe('createContext', () => { rerender(); expect(scratch.innerHTML).to.equal('

hi

'); }); + + it('should not call sCU on context update', () => { + const Ctx = createContext('foo'); + + /** @type {(s: string) => void} */ + let update; + class App extends Component { + constructor(props) { + super(props); + this.state = { foo: 'foo' }; + update = v => this.setState({ foo: v }); + } + render() { + return ( + + + + ); + } + } + + const spy = sinon.spy(); + + class Child extends Component { + static contextType = Ctx; + + shouldComponentUpdate() { + spy(); + return false; + } + + render() { + return

{this.context}

; + } + } + + render(, scratch); + expect(scratch.textContent).to.equal('foo'); + + update('bar'); + rerender(); + expect(scratch.textContent).to.equal('bar'); + expect(spy).not.to.be.called; + }); });