Skip to content

Commit

Permalink
Add custom useSignalEffect
Browse files Browse the repository at this point in the history
  • Loading branch information
DAreRodz authored and gziolo committed May 5, 2023
1 parent 0d88c77 commit 142050c
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
5 changes: 3 additions & 2 deletions packages/block-library/src/utils/interactivity/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
* External dependencies
*/
import { useContext, useMemo, useEffect } from 'preact/hooks';
import { useSignalEffect } from '@preact/signals';
import { deepSignal, peek } from 'deepsignal';

/**
* Internal dependencies
*/
import { useSignalEffect } from './utils';
import { directive } from './hooks';

const isObject = ( item ) =>
Expand Down Expand Up @@ -76,7 +77,7 @@ export default () => {
const contextValue = useContext( context );
Object.entries( on ).forEach( ( [ name, path ] ) => {
element.props[ `on${ name }` ] = ( event ) => {
return evaluate( path, { event, context: contextValue } );
evaluate( path, { event, context: contextValue } );
};
} );
} );
Expand Down
46 changes: 46 additions & 0 deletions packages/block-library/src/utils/interactivity/utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,49 @@
/**
* External dependencies
*/
import { useRef, useEffect } from 'preact/hooks';
import { effect } from '@preact/signals';

function afterNextFrame( callback ) {
const done = () => {
window.cancelAnimationFrame( raf );
setTimeout( callback );
};
const raf = window.requestAnimationFrame( done );
}

// Using the mangled properties:
// this.c: this._callback
// this.x: this._compute
// https://github.com/preactjs/signals/blob/main/mangle.json
function createFlusher( compute, notify ) {
let flush;
const dispose = effect( function () {
flush = this.c.bind( this );
this.x = compute;
this.c = notify;
return compute();
} );
return { flush, dispose };
}

// Version of `useSignalEffect` with a `useEffect`-like execution. This hook
// implementation comes from this PR:
// https://github.com/preactjs/signals/pull/290.
//
// We need to include it here in this repo until the mentioned PR is merged.
export function useSignalEffect( cb ) {
const callback = useRef( cb );
callback.current = cb;

useEffect( () => {
const execute = () => callback.current();
const notify = () => afterNextFrame( eff.flush );
const eff = createFlusher( execute, notify );
return eff.dispose;
}, [] );
}

// For wrapperless hydration.
// See https://gist.github.com/developit/f4c67a2ede71dc2fab7f357f39cff28c
export const createRootFragment = ( parent, replaceNode ) => {
Expand Down

0 comments on commit 142050c

Please sign in to comment.