diff --git a/src/components/DeviceSize/Provider.js b/src/components/DeviceSize/Provider.js index b4fc958c9..cf176cfe1 100644 --- a/src/components/DeviceSize/Provider.js +++ b/src/components/DeviceSize/Provider.js @@ -8,13 +8,32 @@ import constants from "../../theme/constants"; export default class DeviceSizeProvider extends React.Component { static propTypes = { children: PropTypes.node.isRequired, + // https://github.com/yannickcr/eslint-plugin-react/issues/1751 + // eslint-disable-next-line fallbackDetection: PropTypes.func, cssOnly: PropTypes.bool }; static defaultProps = { fallbackDetection: null, cssOnly: false }; - initialState = { isSmall: true }; // eslint-disable-line + initialState = { isInitialized: false, isSmall: true }; // eslint-disable-line + + static getDerivedStateFromProps(props, state) { + if (!state.isInitialized && typeof props.fallbackDetection === "function") { + const fallbackDetectionResult = props.fallbackDetection(); + + if ( + typeof fallbackDetectionResult === "object" && + fallbackDetectionResult !== null + ) { + return { + ...fallbackDetectionResult + }; + } + } + + return null; + } state = this.initialState; @@ -58,6 +77,7 @@ export default class DeviceSizeProvider extends React.Component { } this.setState(() => ({ + isInitialized: true, isSmall: this.smallMedia.matches && !this.mediumMedia.matches, isMedium: this.mediumMedia.matches && !this.largeMedia.matches, isLarge: this.largeMedia.matches && !this.xLargeMedia.matches, @@ -74,12 +94,6 @@ export default class DeviceSizeProvider extends React.Component { }; render() { - const { fallbackDetection } = this.props; - const val = fallbackDetection ? fallbackDetection() : this.state; - return ( - - {this.props.children} - - ); + return {this.props.children}; } } diff --git a/src/components/DeviceSize/__test__/Provider.spec.js b/src/components/DeviceSize/__test__/Provider.spec.js index 676499994..7bacb4342 100644 --- a/src/components/DeviceSize/__test__/Provider.spec.js +++ b/src/components/DeviceSize/__test__/Provider.spec.js @@ -76,4 +76,25 @@ describe("DeviceSize", () => { expect(removeListener).toHaveBeenCalled(); }); }); + + describe("getDerivedStateFromProps()", () => { + it("should use fallbackDetection data to populate derived state", () => { + const fallbackDevices = { isSmall: false, isLarge: true }; + const fallbackDetection = jest + .fn() + .mockImplementation(() => fallbackDevices); + + const derivedState = Provider.getDerivedStateFromProps( + { + fallbackDetection + }, + { + isInitialized: false + } + ); + + expect(fallbackDetection).toHaveBeenCalled(); + expect(derivedState).toEqual(fallbackDevices); + }); + }); });