diff --git a/packages/react/src/React.js b/packages/react/src/React.js
index 61a59f83c530b..9872c13ce2061 100644
--- a/packages/react/src/React.js
+++ b/packages/react/src/React.js
@@ -17,6 +17,7 @@ import {
createFactory,
cloneElement,
isValidElement,
+ isValidFragmentElement,
} from './ReactElement';
import {
createElementWithValidation,
@@ -44,6 +45,7 @@ const React = {
cloneElement: __DEV__ ? cloneElementWithValidation : cloneElement,
createFactory: __DEV__ ? createFactoryWithValidation : createFactory,
isValidElement: isValidElement,
+ isValidFragmentElement: isValidFragmentElement,
version: ReactVersion,
diff --git a/packages/react/src/ReactElement.js b/packages/react/src/ReactElement.js
index a988bfb800033..e42f68e864aed 100644
--- a/packages/react/src/ReactElement.js
+++ b/packages/react/src/ReactElement.js
@@ -6,7 +6,7 @@
*/
import warning from 'fbjs/lib/warning';
-import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
+import {REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';
import ReactCurrentOwner from './ReactCurrentOwner';
@@ -368,3 +368,13 @@ export function isValidElement(object) {
object.$$typeof === REACT_ELEMENT_TYPE
);
}
+
+/**
+ * Verifies the object is a ReactFragmentElement.
+ * @param {?object} object
+ * @return {boolean} True if `object` is a valid fragment component.
+ * @final
+ */
+export function isValidFragmentElement(object) {
+ return isValidElement(object) && object.type === REACT_FRAGMENT_TYPE;
+}
diff --git a/packages/react/src/ReactElementValidator.js b/packages/react/src/ReactElementValidator.js
index bdf67881a77fb..1ba2c8f50f723 100644
--- a/packages/react/src/ReactElementValidator.js
+++ b/packages/react/src/ReactElementValidator.js
@@ -273,7 +273,6 @@ function validateFragmentProps(fragment) {
getStackAddendum(),
);
}
-
currentlyValidatingElement = null;
}
diff --git a/packages/react/src/__tests__/ReactElement-test.js b/packages/react/src/__tests__/ReactElement-test.js
index 5790767e5b5a3..8a114722a823d 100644
--- a/packages/react/src/__tests__/ReactElement-test.js
+++ b/packages/react/src/__tests__/ReactElement-test.js
@@ -314,6 +314,52 @@ describe('ReactElement', () => {
expect(React.isValidElement(JSON.parse(jsonElement))).toBe(true);
});
+ // NOTE: We're explicitly not using JSX here. This is intended to test
+ // classic JS without JSX.
+ it('identifies valid fragment elements', () => {
+ // because we set global.Symbol = undefined in the beforeEach of some tests
+ // so we can't use `Object.keys` together with `for of` syntax
+ // in the 'validateFragmentProps' function of ReactElementValidator.js
+ // it will throw TypeError: can not read property 'interator' of undefined
+ // so we have to set it to orgin value
+ global.Symbol = originalSymbol;
+
+ class Component extends React.Component {
+ render() {
+ return React.createElement(
+ React.Fragment,
+ null,
+ React.createElement('div'),
+ );
+ }
+ }
+
+ expect(
+ React.isValidFragmentElement(
+ React.createElement(React.Fragment, null, React.createElement('div')),
+ ),
+ ).toEqual(true);
+
+ expect(
+ React.isValidFragmentElement(React.createElement(Component)),
+ ).toEqual(false);
+ expect(React.isValidFragmentElement(null)).toEqual(false);
+ expect(React.isValidFragmentElement(true)).toEqual(false);
+ expect(React.isValidFragmentElement({})).toEqual(false);
+ expect(React.isValidFragmentElement('string')).toEqual(false);
+ expect(React.isValidFragmentElement(React.createFactory('div'))).toEqual(
+ false,
+ );
+ expect(React.isValidFragmentElement(Component)).toEqual(false);
+ expect(
+ React.isValidFragmentElement({type: React.Fragment, props: {}}),
+ ).toEqual(false);
+
+ const jsonElement = JSON.stringify(React.createElement(React.Fragment));
+ expect(jsonElement).not.toHaveProperty('type');
+ expect(React.isValidFragmentElement(JSON.parse(jsonElement))).toBe(true);
+ });
+
// NOTE: We're explicitly not using JSX here. This is intended to test
// classic JS without JSX.
it('is indistinguishable from a plain object', () => {
diff --git a/packages/react/src/__tests__/ReactJSXElement-test.js b/packages/react/src/__tests__/ReactJSXElement-test.js
index 920167125f8c4..1be6db355bca2 100644
--- a/packages/react/src/__tests__/ReactJSXElement-test.js
+++ b/packages/react/src/__tests__/ReactJSXElement-test.js
@@ -165,6 +165,21 @@ describe('ReactJSXElement', () => {
expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);
});
+ it('identifies valid fragment elements', () => {
+ expect(React.isValidFragmentElement(