Skip to content

Instantly share code, notes, and snippets.

@aduth
Created May 31, 2017 23:53
Show Gist options
  • Save aduth/799793b48d149856ce3d6aac06804f5e to your computer and use it in GitHub Desktop.
Save aduth/799793b48d149856ce3d6aac06804f5e to your computer and use it in GitHub Desktop.
Simple Preact / React Slot & Fill Pattern
/**
* External dependencies
*/
import { createElement, Component } from 'preact';
const slots = {};
const fills = {};
let toUpdate = [],
nextUpdate;
function performUpdate() {
toUpdate.forEach( ( name ) => {
slots[ name ].forEach( ( slot ) => {
slot.setState( {
fills: fills[ name ] || []
} );
} );
} );
toUpdate = [];
}
function queueUpdate( name ) {
clearTimeout( nextUpdate );
toUpdate.push( name );
nextUpdate = setTimeout( performUpdate );
}
export class Fill extends Component {
componentWillMount() {
const { name } = this.props;
if ( ! fills[ name ] ) {
fills[ name ] = [];
}
fills[ name ].push( this );
queueUpdate( name );
}
componentDidUpdate() {
queueUpdate( this.props.name );
}
componentWillUnmount() {
const { name } = this.props;
const index = fills[ name ].indexOf( this );
if ( index >= 0 ) {
fills[ name ].splice( index, 1 );
}
queueUpdate( name );
}
render() {
return null;
}
}
export class Slot extends Component {
constructor( { name } ) {
super( ...arguments );
if ( ! slots[ name ] ) {
slots[ name ] = [];
}
slots[ name ].push( this );
this.state = {
fills: fills[ name ] || []
};
}
render() {
const content = this.state.fills.map( ( fill ) => (
fill.props.children
) );
return createElement( 'div', null, content );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment