diff --git a/packages/data/src/components/use-select/index.js b/packages/data/src/components/use-select/index.js index 5767b375cf3e71..bc9d2f71bdedda 100644 --- a/packages/data/src/components/use-select/index.js +++ b/packages/data/src/components/use-select/index.js @@ -153,6 +153,7 @@ export default function useSelect( mapSelect, deps ) { let mapOutput; + let selectorRan = false; if ( _mapSelect ) { mapOutput = latestMapOutput.current; const hasReplacedRegistry = latestRegistry.current !== registry; @@ -168,6 +169,7 @@ export default function useSelect( mapSelect, deps ) { ) { try { mapOutput = wrapSelect( _mapSelect ); + selectorRan = true; } catch ( error ) { let errorMessage = `An error occurred while running 'mapSelect': ${ error.message }`; @@ -191,7 +193,9 @@ export default function useSelect( mapSelect, deps ) { latestRegistry.current = registry; latestMapSelect.current = _mapSelect; latestIsAsync.current = isAsync; - latestMapOutput.current = mapOutput; + if ( selectorRan ) { + latestMapOutput.current = mapOutput; + } latestMapOutputError.current = undefined; } ); @@ -310,9 +314,11 @@ export function useSuspenseSelect( mapSelect, deps ) { const hasReplacedMapSelect = latestMapSelect.current !== _mapSelect; const hasLeftAsyncMode = latestIsAsync.current && ! isAsync; + let selectorRan = false; if ( hasReplacedRegistry || hasReplacedMapSelect || hasLeftAsyncMode ) { try { mapOutput = wrapSelect( _mapSelect ); + selectorRan = true; } catch ( error ) { mapOutputError = error; } @@ -322,7 +328,9 @@ export function useSuspenseSelect( mapSelect, deps ) { latestRegistry.current = registry; latestMapSelect.current = _mapSelect; latestIsAsync.current = isAsync; - latestMapOutput.current = mapOutput; + if ( selectorRan ) { + latestMapOutput.current = mapOutput; + } latestMapOutputError.current = mapOutputError; } ); diff --git a/packages/data/src/components/use-select/test/index.js b/packages/data/src/components/use-select/test/index.js index 6e0471f7b4449d..3337ed976139d2 100644 --- a/packages/data/src/components/use-select/test/index.js +++ b/packages/data/src/components/use-select/test/index.js @@ -1,12 +1,12 @@ /** * External dependencies */ -import { act, render } from '@testing-library/react'; +import { act, render, fireEvent } from '@testing-library/react'; /** * WordPress dependencies */ -import { useState, useReducer } from '@wordpress/element'; +import { Component, useState, useReducer } from '@wordpress/element'; /** * Internal dependencies @@ -434,6 +434,63 @@ describe( 'useSelect', () => { ); } ); + it( 'captures state changes scheduled between render and effect', () => { + registry.registerStore( 'store-1', counterStore ); + + class ChildComponent extends Component { + componentDidUpdate( prevProps ) { + if ( + this.props.childShouldDispatch && + this.props.childShouldDispatch !== + prevProps.childShouldDispatch + ) { + registry.dispatch( 'store-1' ).increment(); + } + } + + render() { + return null; + } + } + + const selectCount1AndDep = jest.fn( ( select ) => ( { + count1: select( 'store-1' ).getCounter(), + } ) ); + + const TestComponent = () => { + const [ childShouldDispatch, setChildShouldDispatch ] = + useState( false ); + const state = useSelect( selectCount1AndDep, [] ); + + return ( + <> +