diff --git a/src/components/component-playground.js b/src/components/component-playground.js index 032199e15..19639fb71 100644 --- a/src/components/component-playground.js +++ b/src/components/component-playground.js @@ -1,4 +1,5 @@ import React, { Component } from 'react'; +import isEmpty from 'lodash/isEmpty'; import PropTypes from 'prop-types'; import styled, { css } from 'react-emotion'; import { defaultCode } from '../utils/playground.default-code'; @@ -138,10 +139,6 @@ function getEnhancedScope(scope = {}) { return { Component, ...scope }; } -// TODO(540): Refactor to non-deprecated lifecycle methods. -// https://github.com/FormidableLabs/spectacle/issues/540 -// - componentWillReceiveProps -// eslint-disable-next-line react/no-deprecated class ComponentPlayground extends Component { constructor() { super(...arguments); @@ -156,26 +153,42 @@ class ComponentPlayground extends Component { }; } + static getDerivedStateFromProps(nextProps, prevState) { + const updatedState = {}; + if (nextProps.code !== prevState.code) { + const code = (nextProps.code || defaultCode).trim(); + updatedState.code = code; + } + if (nextProps.scope !== prevState.scope) { + const scope = getEnhancedScope(nextProps.scope); + updatedState.scope = scope; + } + return isEmpty(updatedState) ? null : updatedState; + } + componentDidMount() { localStorage.setItem(STORAGE_KEY, this.state.code); window.addEventListener('storage', this.syncCode); } - componentWillReceiveProps(nextProps) { - if (nextProps.code !== this.props.code) { - const code = (this.props.code || defaultCode).trim(); - this.setState({ code }); - } - if (nextProps.scope !== this.props.scope) { - const scope = getEnhancedScope(nextProps.scope); - this.setState({ scope }); - } + componentDidUpdate() { + this.playgroundSetState(); } componentWillUnmount() { window.removeEventListener('storage', this.syncCode); } + playgroundSetState() { + if (this.props.code) { + const code = (this.props.code || defaultCode).trim(); + this.setState({ code }); + } + if (this.props.scope) { + const scope = getEnhancedScope(this.props.scope); + this.setState({ scope }); + } + } onKeyUp(evt) { evt.stopPropagation(); diff --git a/src/components/heading.js b/src/components/heading.js index 3d76d5fc5..1b9afe014 100644 --- a/src/components/heading.js +++ b/src/components/heading.js @@ -51,10 +51,6 @@ const dynamicStyledHeaders = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].reduce( {} ); -// TODO(540): Refactor to non-deprecated lifecycle methods. -// https://github.com/FormidableLabs/spectacle/issues/540 -// - componentWillReceiveProps -// eslint-disable-next-line react/no-deprecated export default class Heading extends Component { constructor() { super(...arguments); @@ -69,9 +65,17 @@ export default class Heading extends Component { window.addEventListener('load', this.resize); window.addEventListener('resize', this.resize); } - componentWillReceiveProps() { - this.resize(); + + static getDerivedStateFromProps(nextProps, prevState) { + return nextProps.fit !== prevState.fit ? { fit: nextProps.fit } : null; + } + + componentDidUpdate(prevProps) { + if (prevProps.fit !== this.props.fit) { + this.resize(); + } } + componentWillUnmount() { window.removeEventListener('load', this.resize); window.removeEventListener('resize', this.resize); diff --git a/src/components/magic-wrapper.js b/src/components/magic-wrapper.js index b092d798f..25e6e43a8 100644 --- a/src/components/magic-wrapper.js +++ b/src/components/magic-wrapper.js @@ -53,10 +53,6 @@ class Context extends Component { } } -// TODO(540): Refactor to non-deprecated lifecycle methods. -// https://github.com/FormidableLabs/spectacle/issues/540 -// - componentWillReceiveProps -// eslint-disable-next-line react/no-deprecated export default class MagicText extends Component { static contextTypes = { contentHeight: PropTypes.number, @@ -86,6 +82,12 @@ export default class MagicText extends Component { renderedChildren: props.children }; } + + static getDerivedStateFromProps(nextProps, prevState) { + return nextProps.magicIndex !== prevState.magicIndex + ? { magicIndex: nextProps.magicIndex } + : null; + } componentDidMount() { this.mounted = true; this.portal = document.getElementById('portal'); @@ -122,42 +124,10 @@ export default class MagicText extends Component { } ); } - componentWillReceiveProps(nextProps) { - if (this.props.magicIndex === nextProps.magicIndex) { - return; - } - ReactDOM.render( - - {nextProps.children} - , - this.portal, - () => { - const styles = {}; - const portalRoot = get(this.portal, 'childNodes[0].childNodes[0]'); - if (portalRoot) { - updateChildren(portalRoot); - buildStyleMap(styles, portalRoot); - this.diffs = detailedDiff(this.portalMap, styles); - this.lastPortalMap = this.portalMap; - this.portalMap = styles; - if (this.mounted) { - this.setState( - { - renderedChildren: nextProps.children - }, - () => { - this.forceUpdate(); - } - ); - } - } - } - ); - } shouldComponentUpdate() { return false; } - componentDidUpdate() { + componentDidUpdate(prevProps) { const containerRoot = get(this.container, 'childNodes[0]'); if (containerRoot) { updateChildren(containerRoot); @@ -199,6 +169,35 @@ export default class MagicText extends Component { } }); } + if (this.props.magicIndex !== prevProps.magicIndex) { + ReactDOM.render( + + {this.props.children} + , + this.portal, + () => { + const styles = {}; + const portalRoot = get(this.portal, 'childNodes[0].childNodes[0]'); + if (portalRoot) { + updateChildren(portalRoot); + buildStyleMap(styles, portalRoot); + this.diffs = detailedDiff(this.portalMap, styles); + this.lastPortalMap = this.portalMap; + this.portalMap = styles; + if (this.mounted) { + this.setState( + { + renderedChildren: this.props.children + }, + () => { + this.forceUpdate(); + } + ); + } + } + } + ); + } this.lastDiffs = this.diffs; } componentWillUnmount() { diff --git a/src/components/manager.js b/src/components/manager.js index dc4f883fc..0fcfaf628 100644 --- a/src/components/manager.js +++ b/src/components/manager.js @@ -57,11 +57,44 @@ const StyledTransition = styled(ReactTransitionGroup)({ transformStyle: 'flat' }); -// TODO(540): Refactor to non-deprecated lifecycle methods. -// https://github.com/FormidableLabs/spectacle/issues/540 -// - componentWillMount -// - componentWillReceiveProps -// eslint-disable-next-line react/no-deprecated +function buildSlideReference(props) { + const slideReference = []; + Children.toArray(props.children).forEach((child, rootIndex) => { + if (child.type === Magic) { + Children.toArray(child.props.children).forEach((setSlide, magicIndex) => { + const reference = { + id: setSlide.props.id || slideReference.length, + magicIndex, + rootIndex + }; + slideReference.push(reference); + }); + } else if (!child.props.hasSlideChildren) { + const reference = { + id: child.props.id || slideReference.length, + rootIndex + }; + if (child.props.goTo) { + reference.goTo = child.props.goTo; + } + slideReference.push(reference); + } else { + child.props.children.forEach((setSlide, setIndex) => { + const reference = { + id: setSlide.props.id || slideReference.length, + setIndex, + rootIndex + }; + if (child.props.goTo) { + reference.goTo = child.props.goTo; + } + slideReference.push(reference); + }); + } + }); + return slideReference; +} + export class Manager extends Component { static displayName = 'Manager'; @@ -146,10 +179,8 @@ export class Manager extends Component { }; } - componentWillMount() { - this.setState({ - slideReference: this._buildSlideReference(this.props) - }); + static getDerivedStateFromProps(nextProps) { + return { slideReference: buildSlideReference(nextProps) }; } componentDidMount() { @@ -163,12 +194,6 @@ export class Manager extends Component { } } - componentWillReceiveProps(nextProps) { - this.setState({ - slideReference: this._buildSlideReference(nextProps) - }); - } - componentDidUpdate() { if ( this.props.globalStyles && @@ -177,6 +202,7 @@ export class Manager extends Component { this.props.dispatch(setGlobalStyle()); } } + componentWillUnmount() { this._detachEvents(); } @@ -670,45 +696,7 @@ export class Manager extends Component { return 0; } - _buildSlideReference(props) { - const slideReference = []; - Children.toArray(props.children).forEach((child, rootIndex) => { - if (child.type === Magic) { - Children.toArray(child.props.children).forEach( - (setSlide, magicIndex) => { - const reference = { - id: setSlide.props.id || slideReference.length, - magicIndex, - rootIndex - }; - slideReference.push(reference); - } - ); - } else if (!child.props.hasSlideChildren) { - const reference = { - id: child.props.id || slideReference.length, - rootIndex - }; - if (child.props.goTo) { - reference.goTo = child.props.goTo; - } - slideReference.push(reference); - } else { - child.props.children.forEach((setSlide, setIndex) => { - const reference = { - id: setSlide.props.id || slideReference.length, - setIndex, - rootIndex - }; - if (child.props.goTo) { - reference.goTo = child.props.goTo; - } - slideReference.push(reference); - }); - } - }); - return slideReference; - } + _getSlideIndex() { let index = parseInt(this.props.route.slide); if (!Number.isFinite(index)) { diff --git a/src/components/notes.js b/src/components/notes.js index 24c3e0344..7ac22d161 100644 --- a/src/components/notes.js +++ b/src/components/notes.js @@ -1,10 +1,6 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -// TODO(540): Refactor to non-deprecated lifecycle methods. -// https://github.com/FormidableLabs/spectacle/issues/540 -// - componentWillMount -// eslint-disable-next-line react/no-deprecated export default class Notes extends Component { static contextTypes = { store: PropTypes.object, @@ -16,7 +12,7 @@ export default class Notes extends Component { children: PropTypes.node.isRequired }; - componentWillMount() { + componentDidMount() { const { store, slideHash: parentSlide, updateNotes } = this.context; const currentSlide = store.getState().route.slide; diff --git a/src/components/text.js b/src/components/text.js index 9af77f06e..dfcbdd16a 100644 --- a/src/components/text.js +++ b/src/components/text.js @@ -35,10 +35,6 @@ const UnfitText = styled.p(({ lineHeight, styles }) => [ styles.user ]); -// TODO(540): Refactor to non-deprecated lifecycle methods. -// https://github.com/FormidableLabs/spectacle/issues/540 -// - componentWillReceiveProps -// eslint-disable-next-line react/no-deprecated export default class Text extends Component { constructor() { super(...arguments); @@ -49,13 +45,20 @@ export default class Text extends Component { }; } + static getDerivedStateFromProps(nextProps, prevState) { + return nextProps.fit !== prevState.fit ? { fit: nextProps.fit } : null; + } + componentDidMount() { this.resize(); window.addEventListener('load', this.resize); window.addEventListener('resize', this.resize); } - componentWillReceiveProps() { - this.resize(); + + componentDidUpdate(prevProps) { + if (prevProps.fit !== this.props.fit) { + this.resize(); + } } componentWillUnmount() { window.removeEventListener('load', this.resize);