From a325563a58f5d5a4258fc190c79fd0b8a2172acf Mon Sep 17 00:00:00 2001 From: Luis Herranz Date: Tue, 22 Aug 2023 11:57:59 +0200 Subject: [PATCH] Interactivity API: merge new server-side rendered context on client-side navigation (#53853) * Add failing test * Fix the test * Add changelog * Fix lint error --- .../directive-context/render.php | 12 +++++++++ .../directive-context/view.js | 27 ++++++++++++++++++- packages/interactivity/CHANGELOG.md | 4 +++ packages/interactivity/src/directives.js | 26 ++++++++++-------- .../interactivity/directives-context.spec.ts | 18 +++++++++++++ 5 files changed, 75 insertions(+), 12 deletions(-) diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php index a9b0402d1b094..0133b251cfc06 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-context/render.php @@ -119,3 +119,15 @@ + +
+
+
+ + + +
diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-context/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-context/view.js index 46483aaa2ea53..f159d5a73caea 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-context/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-context/view.js @@ -1,5 +1,18 @@ ( ( { wp } ) => { - const { store } = wp.interactivity; + const { store, navigate } = wp.interactivity; + + const html = ` +
+
+
+ + + +
`; store( { derived: { @@ -17,6 +30,18 @@ toggleContextText: ( { context } ) => { context.text = context.text === 'Text 1' ? 'Text 2' : 'Text 1'; }, + toggleText: ( { context } ) => { + context.text = "changed dynamically"; + }, + addNewText: ( { context } ) => { + context.newText = 'some new text'; + }, + navigate: () => { + navigate( window.location, { + force: true, + html, + } ); + } }, } ); } )( window ); diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index b521bb704085d..33fbe2017ef0c 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancements + +- Merge new server-side rendered context on client-side navigation. ([#53853](https://github.com/WordPress/gutenberg/pull/53853)) + ## 2.1.0 (2023-08-16) ### New Features diff --git a/packages/interactivity/src/directives.js b/packages/interactivity/src/directives.js index 16789bd9da052..61fd5ab26f959 100644 --- a/packages/interactivity/src/directives.js +++ b/packages/interactivity/src/directives.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { useContext, useMemo, useEffect } from 'preact/hooks'; +import { useContext, useMemo, useEffect, useRef } from 'preact/hooks'; import { deepSignal, peek } from 'deepsignal'; /** @@ -36,20 +36,24 @@ export default () => { 'context', ( { directives: { - context: { default: context }, + context: { default: newContext }, }, props: { children }, - context: inherited, + context: inheritedContext, } ) => { - const { Provider } = inherited; - const inheritedValue = useContext( inherited ); - const value = useMemo( () => { - const localValue = deepSignal( context ); - mergeDeepSignals( localValue, inheritedValue ); - return localValue; - }, [ context, inheritedValue ] ); + const { Provider } = inheritedContext; + const inheritedValue = useContext( inheritedContext ); + const currentValue = useRef( deepSignal( {} ) ); + currentValue.current = useMemo( () => { + const newValue = deepSignal( newContext ); + mergeDeepSignals( newValue, currentValue.current ); + mergeDeepSignals( newValue, inheritedValue ); + return newValue; + }, [ newContext, inheritedValue ] ); - return { children }; + return ( + { children } + ); }, { priority: 5 } ); diff --git a/test/e2e/specs/interactivity/directives-context.spec.ts b/test/e2e/specs/interactivity/directives-context.spec.ts index 5c74e8054bf19..01e28049a57ff 100644 --- a/test/e2e/specs/interactivity/directives-context.spec.ts +++ b/test/e2e/specs/interactivity/directives-context.spec.ts @@ -162,4 +162,22 @@ test.describe( 'data-wp-context', () => { await expect( element ).toHaveText( 'Text 1' ); await expect( element ).toHaveAttribute( 'value', 'Text 1' ); } ); + + test( 'should replace values on navigation', async ( { page } ) => { + const element = page.getByTestId( 'navigation text' ); + await expect( element ).toHaveText( 'first page' ); + await page.getByTestId( 'toggle text' ).click(); + await expect( element ).toHaveText( 'changed dynamically' ); + await page.getByTestId( 'navigate' ).click(); + await expect( element ).toHaveText( 'second page' ); + } ); + + test( 'should preserve the previous context values', async ( { page } ) => { + const element = page.getByTestId( 'navigation new text' ); + await expect( element ).toHaveText( '' ); + await page.getByTestId( 'add new text' ).click(); + await expect( element ).toHaveText( 'some new text' ); + await page.getByTestId( 'navigate' ).click(); + await expect( element ).toHaveText( 'some new text' ); + } ); } );