/* eslint-disable react/react-in-jsx-scope, react/jsx-no-undef */
/* global React ReactCache ReactDOM SchedulerTracing ScheduleTracing */
const apps = [];
const pieces = React.version.split('.');
const major =
pieces[0] === '0' ? parseInt(pieces[1], 10) : parseInt(pieces[0], 10);
const minor =
pieces[0] === '0' ? parseInt(pieces[2], 10) : parseInt(pieces[1], 10);
// Convenience wrapper to organize API features in DevTools.
function Feature({children, label, version}) {
return (
{label}
{version}
{children}
);
}
// Simplify interaction tracing for tests below.
let trace = null;
if (typeof SchedulerTracing !== 'undefined') {
trace = SchedulerTracing.unstable_trace;
} else if (typeof ScheduleTracing !== 'undefined') {
trace = ScheduleTracing.unstable_trace;
} else {
trace = (_, __, callback) => callback();
}
// https://github.com/facebook/react/blob/main/CHANGELOG.md
switch (major) {
case 16:
switch (minor) {
case 7:
if (typeof React.useState === 'function') {
// Hooks
function Hooks() {
const [count, setCount] = React.useState(0);
const incrementCount = React.useCallback(
() => setCount(count + 1),
[count]
);
return (
count: {count}{' '}
increment
);
}
apps.push(
);
}
case 6:
// memo
function LabelComponent({label}) {
return {label} ;
}
const AnonymousMemoized = React.memo(({label}) => (
{label}
));
const Memoized = React.memo(LabelComponent);
const CustomMemoized = React.memo(LabelComponent);
CustomMemoized.displayName = 'MemoizedLabelFunction';
apps.push(
);
// Suspense
const loadResource = ([text, ms]) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(text);
}, ms);
});
};
const getResourceKey = ([text, ms]) => text;
const Resource = ReactCache.unstable_createResource(
loadResource,
getResourceKey
);
class Suspending extends React.Component {
state = {useSuspense: false};
useSuspense = () => this.setState({useSuspense: true});
render() {
if (this.state.useSuspense) {
const text = Resource.read(['loaded', 2000]);
return text;
} else {
return load data ;
}
}
}
apps.push(
loading...}>
);
// lazy
const LazyWithDefaultProps = React.lazy(
() =>
new Promise(resolve => {
function FooWithDefaultProps(props) {
return (
{props.greeting}, {props.name}
);
}
FooWithDefaultProps.defaultProps = {
name: 'World',
greeting: 'Bonjour',
};
resolve({
default: FooWithDefaultProps,
});
})
);
apps.push(
loading...}>
);
case 5:
case 4:
// unstable_Profiler
class ProfilerChild extends React.Component {
state = {count: 0};
incrementCount = () =>
this.setState(prevState => ({count: prevState.count + 1}));
render() {
return (
count: {this.state.count}{' '}
increment
);
}
}
const onRender = (...args) => {};
const Profiler = React.unstable_Profiler || React.Profiler;
apps.push(
);
case 3:
// createContext()
const LocaleContext = React.createContext();
LocaleContext.displayName = 'LocaleContext';
const ThemeContext = React.createContext();
apps.push(
{theme => theme: {theme}
}
{locale => locale: {locale}
}
);
// forwardRef()
const AnonymousFunction = React.forwardRef((props, ref) => (
{props.children}
));
const NamedFunction = React.forwardRef(function named(props, ref) {
return {props.children}
;
});
const CustomName = React.forwardRef((props, ref) => (
{props.children}
));
CustomName.displayName = 'CustomNameForwardRef';
apps.push(
AnonymousFunction
NamedFunction
CustomName
);
// StrictMode
class StrictModeChild extends React.Component {
render() {
return 'StrictModeChild';
}
}
apps.push(
);
// unstable_AsyncMode (later renamed to unstable_ConcurrentMode, then ConcurrentMode)
const ConcurrentMode =
React.ConcurrentMode ||
React.unstable_ConcurrentMode ||
React.unstable_AsyncMode;
apps.push(
unstable_AsyncMode was added in 16.3, renamed to
unstable_ConcurrentMode in 16.5, and then renamed to
ConcurrentMode in 16.7
);
case 2:
// Fragment
apps.push(
one
two
);
case 1:
case 0:
default:
break;
}
break;
case 15:
break;
case 14:
break;
default:
break;
}
function Even() {
return (even) ;
}
// Simple stateful app shared by all React versions
class SimpleApp extends React.Component {
state = {count: 0};
incrementCount = () => {
const updaterFn = prevState => ({count: prevState.count + 1});
trace('Updating count', performance.now(), () => this.setState(updaterFn));
};
render() {
const {count} = this.state;
return (
{count % 2 === 0 ? (
count: {count}
) : (
count: {count}
)}{' '}
increment
);
}
}
apps.push(
);
// This component, with the version prop, helps organize DevTools at a glance.
function TopLevelWrapperForDevTools({version}) {
let header = React {version} ;
if (version.includes('canary')) {
const commitSha = version.match(/.+canary-(.+)/)[1];
header = (
);
} else if (version.includes('alpha')) {
header = React next ;
}
return (
{header}
{apps}
);
}
TopLevelWrapperForDevTools.displayName = 'React';
ReactDOM.render(
,
document.getElementById('root')
);