diff --git a/hooks/src/index.js b/hooks/src/index.js index e70353ba05..92a05f0a54 100644 --- a/hooks/src/index.js +++ b/hooks/src/index.js @@ -249,7 +249,7 @@ export function useReducer(reducer, initialState, init) { // We check whether we have components with a nextValue set that // have values that aren't equal to one another this pushes // us to update further down the tree - let shouldUpdate = false; + let shouldUpdate = hookState._component.props !== p; stateHooks.forEach(hookItem => { if (hookItem._nextValue) { const currentValue = hookItem._value[0]; @@ -259,11 +259,9 @@ export function useReducer(reducer, initialState, init) { } }); - return shouldUpdate || hookState._component.props !== p - ? prevScu - ? prevScu.call(this, p, s, c) - : true - : false; + return prevScu + ? prevScu.call(this, p, s, c) || shouldUpdate + : shouldUpdate; } currentComponent.shouldComponentUpdate = updateHookState; diff --git a/hooks/test/browser/useState.test.js b/hooks/test/browser/useState.test.js index 58b152afc8..ffa99e7902 100644 --- a/hooks/test/browser/useState.test.js +++ b/hooks/test/browser/useState.test.js @@ -1,5 +1,5 @@ import { setupRerender, act } from 'preact/test-utils'; -import { createElement, render, createContext } from 'preact'; +import { createElement, render, createContext, Component } from 'preact'; import { useState, useContext, useEffect } from 'preact/hooks'; import { setupScratch, teardown } from '../../../test/_util/helpers'; @@ -371,4 +371,46 @@ describe('useState', () => { rerender(); expect(scratch.innerHTML).to.equal('
hello world!!!
'); }); + + describe('Global sCU', () => { + let prevScu; + before(() => { + prevScu = Component.prototype.shouldComponentUpdate; + Component.prototype.shouldComponentUpdate = () => { + return true; + }; + }); + + after(() => { + Component.prototype.shouldComponentUpdate = prevScu; + }); + + it('correctly updates with multiple state updates', () => { + let simulateClick; + + let renders = 0; + function TestWidget() { + renders++; + const [saved, setSaved] = useState(false); + + simulateClick = () => { + setSaved(true); + setSaved(false); + }; + + return