| /** |
| * @fileoverview Prevent passing of children as props |
| * @author Benjamin Stepp |
| */ |
| |
| 'use strict'; |
| |
| const docsUrl = require('../util/docsUrl'); |
| |
| // ------------------------------------------------------------------------------ |
| // Helpers |
| // ------------------------------------------------------------------------------ |
| |
| /** |
| * Checks if the node is a createElement call with a props literal. |
| * @param {ASTNode} node - The AST node being checked. |
| * @returns {Boolean} - True if node is a createElement call with a props |
| * object literal, False if not. |
| */ |
| function isCreateElementWithProps(node) { |
| return node.callee && |
| node.callee.type === 'MemberExpression' && |
| node.callee.property.name === 'createElement' && |
| node.arguments.length > 1 && |
| node.arguments[1].type === 'ObjectExpression'; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| // Rule Definition |
| // ------------------------------------------------------------------------------ |
| |
| module.exports = { |
| meta: { |
| docs: { |
| description: 'Prevent passing of children as props.', |
| category: 'Best Practices', |
| recommended: true, |
| url: docsUrl('no-children-prop') |
| }, |
| schema: [] |
| }, |
| create(context) { |
| return { |
| JSXAttribute(node) { |
| if (node.name.name !== 'children') { |
| return; |
| } |
| |
| context.report({ |
| node, |
| message: 'Do not pass children as props. Instead, nest children between the opening and closing tags.' |
| }); |
| }, |
| CallExpression(node) { |
| if (!isCreateElementWithProps(node)) { |
| return; |
| } |
| |
| const props = node.arguments[1].properties; |
| const childrenProp = props.find(prop => prop.key && prop.key.name === 'children'); |
| |
| if (childrenProp) { |
| context.report({ |
| node, |
| message: 'Do not pass children as props. Instead, pass them as additional arguments to React.createElement.' |
| }); |
| } |
| } |
| }; |
| } |
| }; |