Skip to content

Commit

Permalink
Update SlotFillProvider to the stable context API (#11123)
Browse files Browse the repository at this point in the history
  • Loading branch information
nosolosw authored Nov 2, 2018
1 parent 3caec34 commit aad371d
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 76 deletions.
36 changes: 19 additions & 17 deletions packages/components/src/popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* External dependencies
*/
import classnames from 'classnames';
import { noop } from 'lodash';

/**
* WordPress dependencies
Expand All @@ -20,7 +19,7 @@ import withConstrainedTabbing from '../higher-order/with-constrained-tabbing';
import PopoverDetectOutside from './detect-outside';
import IconButton from '../icon-button';
import ScrollLock from '../scroll-lock';
import { Slot, Fill } from '../slot-fill';
import { Slot, Fill, Consumer } from '../slot-fill';

const FocusManaged = withConstrainedTabbing( withFocusReturn( ( { children } ) => children ) );

Expand Down Expand Up @@ -302,17 +301,24 @@ class Popover extends Component {
content = <FocusManaged>{ content }</FocusManaged>;
}

// In case there is no slot context in which to render, default to an
// in-place rendering.
const { getSlot } = this.context;
if ( getSlot && getSlot( SLOT_NAME ) ) {
content = <Fill name={ SLOT_NAME }>{ content }</Fill>;
}

return <span ref={ this.anchorNode }>
{ content }
{ isMobile && expandOnMobile && <ScrollLock /> }
</span>;
return (
<Consumer>
{ ( { getSlot } ) => {
// In case there is no slot context in which to render,
// default to an in-place rendering.
if ( getSlot && getSlot( SLOT_NAME ) ) {
content = <Fill name={ SLOT_NAME }>{ content }</Fill>;
}

return (
<span ref={ this.anchorNode }>
{ content }
{ isMobile && expandOnMobile && <ScrollLock /> }
</span>
);
} }
</Consumer>
);
}
}

Expand All @@ -323,10 +329,6 @@ Popover.defaultProps = {

const PopoverContainer = Popover;

PopoverContainer.contextTypes = {
getSlot: noop,
};

PopoverContainer.Slot = () => <Slot bubblesVirtually name={ SLOT_NAME } />;

export default PopoverContainer;
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
/**
* External dependencies
*/
import { pick, sortBy, forEach, without, noop } from 'lodash';
import { sortBy, forEach, without } from 'lodash';

/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { Component, createContext } from '@wordpress/element';

const { Provider, Consumer } = createContext( {
registerSlot: () => {},
unregisterSlot: () => {},
registerFill: () => {},
unregisterFill: () => {},
getSlot: () => {},
getFills: () => {},
} );

class SlotFillProvider extends Component {
constructor() {
Expand All @@ -21,17 +30,14 @@ class SlotFillProvider extends Component {

this.slots = {};
this.fills = {};
}

getChildContext() {
return pick( this, [
'registerSlot',
'registerFill',
'unregisterSlot',
'unregisterFill',
'getSlot',
'getFills',
] );
this.state = {
registerSlot: this.registerSlot,
unregisterSlot: this.unregisterSlot,
registerFill: this.registerFill,
unregisterFill: this.unregisterFill,
getSlot: this.getSlot,
getFills: this.getFills,
};
}

registerSlot( name, slot ) {
Expand Down Expand Up @@ -94,17 +100,13 @@ class SlotFillProvider extends Component {
}

render() {
return this.props.children;
return (
<Provider value={ this.state }>
{ this.props.children }
</Provider>
);
}
}

SlotFillProvider.childContextTypes = {
registerSlot: noop,
unregisterSlot: noop,
registerFill: noop,
unregisterFill: noop,
getSlot: noop,
getFills: noop,
};

export default SlotFillProvider;
export { Consumer };
41 changes: 24 additions & 17 deletions packages/components/src/slot-fill/fill.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
/**
* External dependencies
*/
import { noop, isFunction } from 'lodash';
import { isFunction } from 'lodash';

/**
* WordPress dependencies
*/
import { Component, createPortal } from '@wordpress/element';

/**
* Internal dependencies
*/
import { Consumer } from './context';

let occurrences = 0;

class Fill extends Component {
class FillComponent extends Component {
constructor() {
super( ...arguments );
this.occurrence = ++occurrences;
}

componentDidMount() {
const { registerFill = noop } = this.context;
const { registerFill } = this.props;

registerFill( this.props.name, this );
}
Expand All @@ -26,25 +31,21 @@ class Fill extends Component {
if ( ! this.occurrence ) {
this.occurrence = ++occurrences;
}
const { getSlot = noop } = this.context;
const { getSlot } = this.props;
const slot = getSlot( this.props.name );
if ( slot && ! slot.props.bubblesVirtually ) {
slot.forceUpdate();
}
}

componentWillUnmount() {
const { unregisterFill = noop } = this.context;
const { unregisterFill } = this.props;

unregisterFill( this.props.name, this );
}

componentDidUpdate( prevProps ) {
const { name } = this.props;
const {
unregisterFill = noop,
registerFill = noop,
} = this.context;
const { name, unregisterFill, registerFill } = this.props;

if ( prevProps.name !== name ) {
unregisterFill( prevProps.name, this );
Expand All @@ -57,8 +58,7 @@ class Fill extends Component {
}

render() {
const { getSlot = noop } = this.context;
const { name } = this.props;
const { name, getSlot } = this.props;
let { children } = this.props;
const slot = getSlot( name );

Expand All @@ -75,10 +75,17 @@ class Fill extends Component {
}
}

Fill.contextTypes = {
getSlot: noop,
registerFill: noop,
unregisterFill: noop,
};
const Fill = ( props ) => (
<Consumer>
{ ( { getSlot, registerFill, unregisterFill } ) => (
<FillComponent
{ ...props }
getSlot={ getSlot }
registerFill={ registerFill }
unregisterFill={ unregisterFill }
/>
) }
</Consumer>
);

export default Fill;
4 changes: 2 additions & 2 deletions packages/components/src/slot-fill/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
*/
import Slot from './slot';
import Fill from './fill';
import Provider from './provider';
import Provider, { Consumer } from './context';

export { Slot };
export { Fill };
export { Provider };
export { Provider, Consumer };

export function createSlotFill( name ) {
const FillComponent = ( props ) => <Fill name={ name } { ...props } />;
Expand Down
38 changes: 22 additions & 16 deletions packages/components/src/slot-fill/slot.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
isString,
map,
negate,
noop,
} from 'lodash';

/**
Expand All @@ -20,31 +19,32 @@ import {
isEmptyElement,
} from '@wordpress/element';

class Slot extends Component {
/**
* Internal dependencies
*/
import { Consumer } from './context';

class SlotComponent extends Component {
constructor() {
super( ...arguments );

this.bindNode = this.bindNode.bind( this );
}

componentDidMount() {
const { registerSlot = noop } = this.context;
const { registerSlot } = this.props;

registerSlot( this.props.name, this );
}

componentWillUnmount() {
const { unregisterSlot = noop } = this.context;
const { unregisterSlot } = this.props;

unregisterSlot( this.props.name, this );
}

componentDidUpdate( prevProps ) {
const { name } = this.props;
const {
unregisterSlot = noop,
registerSlot = noop,
} = this.context;
const { name, unregisterSlot, registerSlot } = this.props;

if ( prevProps.name !== name ) {
unregisterSlot( prevProps.name );
Expand All @@ -57,8 +57,7 @@ class Slot extends Component {
}

render() {
const { children, name, bubblesVirtually = false, fillProps = {} } = this.props;
const { getFills = noop } = this.context;
const { children, name, bubblesVirtually = false, fillProps = {}, getFills } = this.props;

if ( bubblesVirtually ) {
return <div ref={ this.bindNode } />;
Expand Down Expand Up @@ -91,10 +90,17 @@ class Slot extends Component {
}
}

Slot.contextTypes = {
registerSlot: noop,
unregisterSlot: noop,
getFills: noop,
};
const Slot = ( props ) => (
<Consumer>
{ ( { registerSlot, unregisterSlot, getFills } ) => (
<SlotComponent
{ ...props }
registerSlot={ registerSlot }
unregisterSlot={ unregisterSlot }
getFills={ getFills }
/>
) }
</Consumer>
);

export default Slot;
2 changes: 1 addition & 1 deletion packages/components/src/slot-fill/test/slot.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import ReactTestRenderer from 'react-test-renderer';
*/
import Slot from '../slot';
import Fill from '../fill';
import Provider from '../provider';
import Provider from '../context';

/**
* WordPress Dependencies
Expand Down

0 comments on commit aad371d

Please sign in to comment.