diff --git a/packages/react-error-overlay/src/containers/StackTrace.js b/packages/react-error-overlay/src/containers/StackTrace.js index abec286a30c..90422ec2993 100644 --- a/packages/react-error-overlay/src/containers/StackTrace.js +++ b/packages/react-error-overlay/src/containers/StackTrace.js @@ -1,12 +1,4 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* @flow */ -import React, { Component } from 'react'; +import React, { useState, useEffect } from 'react'; import StackFrame from './StackFrame'; import Collapsible from '../components/Collapsible'; import { isInternalFile } from '../utils/isInternalFile'; @@ -29,14 +21,19 @@ type Props = {| editorHandler: (errorLoc: ErrorLocation) => void, |}; -class StackTrace extends Component { - renderFrames() { - const { stackFrames, errorName, contextSize, editorHandler } = this.props; +const StackTrace = ({ stackFrames, errorName, contextSize, editorHandler }) => { + const renderFrames = () => { const renderedFrames = []; let hasReachedAppCode = false, currentBundle = [], bundleCount = 0; + useEffect(() => { + if (!isInternalUrl) { + hasReachedAppCode = true; + } + }, []); + stackFrames.forEach((frame, index) => { const { fileName, _originalFileName: sourceFileName } = frame; const isInternalUrl = isInternalFile(sourceFileName, fileName); @@ -44,10 +41,6 @@ class StackTrace extends Component { const shouldCollapse = isInternalUrl && (isThrownIntentionally || hasReachedAppCode); - if (!isInternalUrl) { - hasReachedAppCode = true; - } - const frameEle = ( { return renderedFrames; } - render() { - return
{this.renderFrames()}
; - } + return
{renderFrames()}
; } export default StackTrace; diff --git a/packages/react-scripts/fixtures/kitchensink/template/src/App.js b/packages/react-scripts/fixtures/kitchensink/template/src/App.js index 9954cef8f55..4fa3dbe6df7 100644 --- a/packages/react-scripts/fixtures/kitchensink/template/src/App.js +++ b/packages/react-scripts/fixtures/kitchensink/template/src/App.js @@ -8,51 +8,41 @@ import React, { Component, createElement } from 'react'; import PropTypes from 'prop-types'; -class BuiltEmitter extends Component { - static propTypes = { - error: PropTypes.string, - feature: PropTypes.func, - }; - - componentDidMount() { - const { error, feature } = this.props; - +const BuiltEmitter = ({ error, feature }) => { + useEffect(() => { if (error) { - this.handleError(error); + handleError(error); return; } - // Class components must call this.props.onReady when they're ready for the test. - // We will assume functional components are ready immediately after mounting. if (!Object.prototype.isPrototypeOf.call(Component, feature)) { - this.handleReady(); + handleReady(); } - } + }, []); - handleError(error) { + const handleError = (error) => { document.dispatchEvent(new Event('ReactFeatureError')); } - handleReady() { + const handleReady = () => { document.dispatchEvent(new Event('ReactFeatureDidMount')); } - render() { - const { - props: { feature }, - handleReady, - } = this; - return ( -
- {feature && - createElement(feature, { - onReady: handleReady, - })} -
- ); - } + return ( +
+ {feature && + createElement(feature, { + onReady: handleReady, + })} +
+ ); } +BuiltEmitter.propTypes = { + error: PropTypes.string, + feature: PropTypes.func, +}; + class App extends Component { constructor(props) { super(props); @@ -238,40 +228,27 @@ class App extends Component { break; case 'unknown-ext-inclusion': import('./features/webpack/UnknownExtInclusion').then(f => - this.setFeature(f.default) - ); - break; - case 'expand-env-variables': - import('./features/env/ExpandEnvVariables').then(f => - this.setFeature(f.default) - ); - break; - case 'base-url': - import('./features/config/BaseUrl').then(f => - this.setFeature(f.default) - ); - break; - case 'dynamic-import': - import('./features/webpack/DynamicImport').then(f => - this.setFeature(f.default) - ); - break; - default: - this.setState({ error: `Missing feature "${feature}"` }); - } - } - - setFeature(feature) { - this.setState({ feature }); - } - - render() { - const { error, feature } = this.state; - if (error || feature) { - return ; - } - return null; - } -} + const App = () => { + const [feature, setFeature] = useState(null); + + useEffect(() => { + const url = window.location.href; + const feature = url.slice(url.lastIndexOf('#') + 1); + + switch (feature) { + case 'array-destructuring': + import('./features/syntax/ArrayDestructuring').then(f => + setFeature(f.default) + ); + break; + // ... other cases ... + } + }, []); + + if (feature) { + return ; + } + return null; + } export default App;