diff --git a/CHANGELOG.md b/CHANGELOG.md
index 47b4fabe41..4e9fc569dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
## Unreleased
+### Added
+* add [`no-namespace`] rule ([#2640] @yacinehmito @ljharb)
+
+[#2640]: https://github.com/yannickcr/eslint-plugin-react/pull/2640
+
## [7.25.3] - 2021.09.19
### Fixed
@@ -3437,6 +3442,7 @@ If you're still not using React 15 you can keep the old behavior by setting the
[`no-find-dom-node`]: docs/rules/no-find-dom-node.md
[`no-is-mounted`]: docs/rules/no-is-mounted.md
[`no-multi-comp`]: docs/rules/no-multi-comp.md
+[`no-namespace`]: docs/rules/no-namespace.md
[`no-redundant-should-component-update`]: docs/rules/no-redundant-should-component-update.md
[`no-render-return-value`]: docs/rules/no-render-return-value.md
[`no-set-state`]: docs/rules/no-set-state.md
diff --git a/README.md b/README.md
index 193920c819..6c5af3db27 100644
--- a/README.md
+++ b/README.md
@@ -145,6 +145,7 @@ Enable the rules that you would like to use.
| ✔ | | [react/no-find-dom-node](docs/rules/no-find-dom-node.md) | Prevent usage of findDOMNode |
| ✔ | | [react/no-is-mounted](docs/rules/no-is-mounted.md) | Prevent usage of isMounted |
| | | [react/no-multi-comp](docs/rules/no-multi-comp.md) | Prevent multiple component definition per file |
+| | | [react/no-namespace](docs/rules/no-namespace.md) | Enforce that namespaces are not used in React elements |
| | | [react/no-redundant-should-component-update](docs/rules/no-redundant-should-component-update.md) | Flag shouldComponentUpdate when extending PureComponent |
| ✔ | | [react/no-render-return-value](docs/rules/no-render-return-value.md) | Prevent usage of the return value of React.render |
| | | [react/no-set-state](docs/rules/no-set-state.md) | Prevent usage of setState |
diff --git a/docs/rules/no-namespace.md b/docs/rules/no-namespace.md
new file mode 100644
index 0000000000..7ba843e6cc
--- /dev/null
+++ b/docs/rules/no-namespace.md
@@ -0,0 +1,29 @@
+# Enforce that namespaces are not used in React elements (react/no-namespace)
+
+Enforces the absence of a namespace in React elements, such as with `svg:circle`, as they are not supported in React.
+
+## Rule Details
+
+The following patterns are considered warnings:
+
+```jsx
+
+```
+
+```jsx
+
+```
+
+The following patterns are **not** considered warnings:
+
+```jsx
+
+```
+
+```jsx
+
+```
+
+## When not to use
+
+If you are not using React.
diff --git a/index.js b/index.js
index 15fa8f0465..198af7b37f 100644
--- a/index.js
+++ b/index.js
@@ -67,6 +67,7 @@ const allRules = {
'no-find-dom-node': require('./lib/rules/no-find-dom-node'),
'no-is-mounted': require('./lib/rules/no-is-mounted'),
'no-multi-comp': require('./lib/rules/no-multi-comp'),
+ 'no-namespace': require('./lib/rules/no-namespace'),
'no-set-state': require('./lib/rules/no-set-state'),
'no-string-refs': require('./lib/rules/no-string-refs'),
'no-redundant-should-component-update': require('./lib/rules/no-redundant-should-component-update'),
diff --git a/lib/rules/no-namespace.js b/lib/rules/no-namespace.js
new file mode 100644
index 0000000000..8694e589c8
--- /dev/null
+++ b/lib/rules/no-namespace.js
@@ -0,0 +1,49 @@
+/**
+ * @fileoverview Enforce that namespaces are not used in React elements
+ * @author Yacine Hmito
+ */
+
+'use strict';
+
+const elementType = require('jsx-ast-utils/elementType');
+const docsUrl = require('../util/docsUrl');
+const isCreateElement = require('../util/isCreateElement');
+
+// ------------------------------------------------------------------------------
+// Rule Definition
+// ------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: 'Enforce that namespaces are not used in React elements',
+ category: 'Possible Errors',
+ recommended: false,
+ url: docsUrl('no-namespace')
+ },
+
+ schema: [{
+ type: 'object',
+ additionalProperties: false
+ }]
+ },
+
+ create(context) {
+ return {
+ CallExpression(node) {
+ if (isCreateElement(node, context) && node.arguments.length > 0 && node.arguments[0].type === 'Literal') {
+ const name = node.arguments[0].value;
+ if (name.indexOf(':') === -1) return undefined;
+ const message = `React component ${name} must not be in a namespace as React does not support them`;
+ context.report({node, message});
+ }
+ },
+ JSXOpeningElement(node) {
+ const name = elementType(node);
+ if (name.indexOf(':') === -1) return undefined;
+ const message = `React component ${name} must not be in a namespace as React does not support them`;
+ context.report({node, message});
+ }
+ };
+ }
+};
diff --git a/tests/lib/rules/no-namespace.js b/tests/lib/rules/no-namespace.js
new file mode 100644
index 0000000000..b7c8c434b7
--- /dev/null
+++ b/tests/lib/rules/no-namespace.js
@@ -0,0 +1,128 @@
+/**
+ * @fileoverview Tests for jsx-no-namespace
+ * @author Yacine Hmito
+ */
+
+'use strict';
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const RuleTester = require('eslint').RuleTester;
+const rule = require('../../../lib/rules/no-namespace');
+
+const parserOptions = {
+ ecmaVersion: 2018,
+ sourceType: 'module',
+ ecmaFeatures: {
+ jsx: true
+ }
+};
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester({parserOptions});
+ruleTester.run('jsx-no-namespace', rule, {
+ valid: [{
+ code: ''
+ }, {
+ code: 'React.createElement("testcomponent")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("testComponent")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("test_component")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("TestComponent")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("object.testcomponent")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("object.testComponent")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("object.test_component")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("object.TestComponent")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("Object.testcomponent")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("Object.testComponent")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("Object.test_component")'
+ }, {
+ code: ''
+ }, {
+ code: 'React.createElement("Object.TestComponent")'
+ }],
+
+ invalid: [{
+ code: '',
+ errors: [{message: 'React component ns:testcomponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: 'React.createElement("ns:testcomponent")',
+ errors: [{message: 'React component ns:testcomponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: '',
+ errors: [{message: 'React component ns:testComponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: 'React.createElement("ns:testComponent")',
+ errors: [{message: 'React component ns:testComponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: '',
+ errors: [{message: 'React component ns:test_component must not be in a namespace as React does not support them'}]
+ }, {
+ code: 'React.createElement("ns:test_component")',
+ errors: [{message: 'React component ns:test_component must not be in a namespace as React does not support them'}]
+ }, {
+ code: '',
+ errors: [{message: 'React component ns:TestComponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: 'React.createElement("ns:TestComponent")',
+ errors: [{message: 'React component ns:TestComponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: '',
+ errors: [{message: 'React component Ns:testcomponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: 'React.createElement("Ns:testcomponent")',
+ errors: [{message: 'React component Ns:testcomponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: '',
+ errors: [{message: 'React component Ns:testComponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: 'React.createElement("Ns:testComponent")',
+ errors: [{message: 'React component Ns:testComponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: '',
+ errors: [{message: 'React component Ns:test_component must not be in a namespace as React does not support them'}]
+ }, {
+ code: 'React.createElement("Ns:test_component")',
+ errors: [{message: 'React component Ns:test_component must not be in a namespace as React does not support them'}]
+ }, {
+ code: '',
+ errors: [{message: 'React component Ns:TestComponent must not be in a namespace as React does not support them'}]
+ }, {
+ code: 'React.createElement("Ns:TestComponent")',
+ errors: [{message: 'React component Ns:TestComponent must not be in a namespace as React does not support them'}]
+ }]
+});