diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ab1bc8583..a12e145c72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,110 @@ # Change Log All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](http://semver.org/). -This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com). +This project adheres to [Semantic Versioning](https://semver.org/). +This change log adheres to standards from [Keep a CHANGELOG](https://keepachangelog.com). ## Unreleased +## [7.29.2] - 2022.02.25 + +### Fixed +* [`jsx-curly-brace-presence`]: avoid warning on curlies containing quote characters ([#3214][] @ljharb) +* [`jsx-indent`]: do not report on non-jsx-returning ternaries that contain null ([#3222][] @ljharb) +* [`jsx-indent`]: properly report on returned ternaries with jsx ([#3222][] @ljharb) +* [`no-array-index-key`]: detect named-imported `cloneElement`/`createElement` ([#3213][] @ljharb) + +[7.29.2]: https://github.com/yannickcr/eslint-plugin-react/compare/v7.29.1...v7.29.2 +[#3222]: https://github.com/yannickcr/eslint-plugin-react/issues/3222 +[#3214]: https://github.com/yannickcr/eslint-plugin-react/issues/3214 +[#3213]: https://github.com/yannickcr/eslint-plugin-react/issues/3213 + +## [7.29.1] - 2022.02.25 + +### Fixed +* [`jsx-key`]: prevent false "missing array key" warning ([#3215][] @ljharb) +* [`jsx-indent`]: avoid checking returns sans jsx ([#3218][] @ljharb) +* [`jsx-key`]: avoid a crash ([#3220][] @ljharb) +* version settings: avoid a crash with an invalid version ([#3219][] @ljharb) + +[7.29.1]: https://github.com/yannickcr/eslint-plugin-react/compare/v7.29.0...v7.29.1 +[#3220]: https://github.com/yannickcr/eslint-plugin-react/issues/3220 +[#3219]: https://github.com/yannickcr/eslint-plugin-react/issues/3219 +[#3218]: https://github.com/yannickcr/eslint-plugin-react/issues/3218 +[#3215]: https://github.com/yannickcr/eslint-plugin-react/issues/3215 + +## [7.29.0] - 2022.02.24 + +### Added +* add [`hook-use-state`] rule to enforce symmetric useState hook variable names ([#2921][] @duncanbeevers) +* [`jsx-no-target-blank`]: Improve fixer with option `allowReferrer` ([#3167][] @apepper) +* [`jsx-curly-brace-presence`]: add "propElementValues" config option ([#3191][] @ljharb) +* add [`iframe-missing-sandbox`] rule ([#2753][] @tosmolka @ljharb) +* [`no-did-mount-set-state`], [`no-did-update-set-state`]: no-op with react >= 16.3 ([#1754][] @ljharb) +* [`jsx-sort-props`]: support multiline prop groups ([#3198][] @duhamelgm) +* [`jsx-key`]: add `warnDuplicates` option to warn on duplicate jsx keys in an array ([#2614][] @ljharb) +* [`jsx-sort-props`]: add `locale` option ([#3002][] @ljharb) + +### Fixed +* [`prop-types`], `propTypes`: add support for exported type inference ([#3163][] @vedadeepta) +* [`no-invalid-html-attribute`]: allow 'shortcut icon' on `link` ([#3174][] @Primajin) +* [`prefer-exact-props`] improve performance for `Identifier` visitor ([#3190][] @meowtec) +* `propTypes`: Handle TSTypeReference in no-unused-prop-type ([#3195][] @niik) +* [`sort-prop-types`]: avoid repeated warnings of the same node/reason ([#519][] @ljharb) +* [`jsx-indent`]: Fix indent handling for closing parentheses ([#620][] @stefanbuck]) +* [`prop-types`/`propTypes`]: follow a returned identifier to see if it is JSX ([#1046][] @ljharb) +* [`no-unused-state`]: TS: support `getDerivedStateFromProps` as an arrow function ([#2061][] @ljharb) +* [`no-array-index-key`]: catch `.toString` and `String()` usage ([#2813][] @RedTn) +* [`function-component-definition`]: do not break on dollar signs ([#3207][] @ljharb) +* [`prefer-stateless-function`]: avoid a crash inside `doctrine` ([#2596][] @ljharb) +* [`prop-types`]: catch infinite loop ([#2861][] @ljharb) +* [`forbid-prop-types`]: properly report name in error message; check undestructured arguments ([#2945][] @ljharb) + +### Changed +* [readme] change [`jsx-runtime`] link from branch to sha ([#3160][] @tatsushitoji) +* [Docs] HTTP => HTTPS ([#3133][] @Schweinepriester) +* [readme] Some grammar fixes ([#3186][] @JJ) +* [Docs] [`jsx-no-target-blank`]: Improve readme ([#3169][] @apepper) +* [Docs] [`display-name`]: improve examples ([#3189][] @golopot) +* [Refactor] [`no-invalid-html-attribute`]: sort HTML_ELEMENTS and messages ([#3182][] @Primajin) +* [Docs] [`forbid-foreign-prop-types`]: document `allowInPropTypes` option ([#1815][] @ljharb) +* [Refactor] [`jsx-sort-default-props`]: remove unnecessary code ([#1817][] @ljharb) +* [Docs] [`jsx-no-target-blank`]: fix syntax highlighting ([#3199][] @shamrin) +* [Docs] [`jsx-key`]: improve example ([#3202][] @chnakamura) +* [Refactor] [`jsx-key`]: use more AST selectors (@ljharb) + +[7.29.0]: https://github.com/yannickcr/eslint-plugin-react/compare/v7.28.0...v7.29.0 +[#3207]: https://github.com/yannickcr/eslint-plugin-react/issues/3207 +[#3202]: https://github.com/yannickcr/eslint-plugin-react/pull/3202 +[#3199]: https://github.com/yannickcr/eslint-plugin-react/pull/3199 +[#3198]: https://github.com/yannickcr/eslint-plugin-react/pull/3198 +[#3195]: https://github.com/yannickcr/eslint-plugin-react/pull/3195 +[#3191]: https://github.com/yannickcr/eslint-plugin-react/pull/3191 +[#3190]: https://github.com/yannickcr/eslint-plugin-react/pull/3190 +[#3189]: https://github.com/yannickcr/eslint-plugin-react/pull/3189 +[#3186]: https://github.com/yannickcr/eslint-plugin-react/pull/3186 +[#3182]: https://github.com/yannickcr/eslint-plugin-react/pull/3182 +[#3174]: https://github.com/yannickcr/eslint-plugin-react/pull/3174 +[#3169]: https://github.com/yannickcr/eslint-plugin-react/pull/3169 +[#3167]: https://github.com/yannickcr/eslint-plugin-react/pull/3167 +[#3163]: https://github.com/yannickcr/eslint-plugin-react/pull/3163 +[#3160]: https://github.com/yannickcr/eslint-plugin-react/pull/3160 +[#3133]: https://github.com/yannickcr/eslint-plugin-react/pull/3133 +[#3002]: https://github.com/yannickcr/eslint-plugin-react/issues/3002 +[#2945]: https://github.com/yannickcr/eslint-plugin-react/issues/2945 +[#2921]: https://github.com/yannickcr/eslint-plugin-react/pull/2921 +[#2861]: https://github.com/yannickcr/eslint-plugin-react/issues/2861 +[#2813]: https://github.com/yannickcr/eslint-plugin-react/pull/2813 +[#2753]: https://github.com/yannickcr/eslint-plugin-react/pull/2753 +[#2614]: https://github.com/yannickcr/eslint-plugin-react/issues/2614 +[#2596]: https://github.com/yannickcr/eslint-plugin-react/issues/2596 +[#2061]: https://github.com/yannickcr/eslint-plugin-react/issues/2061 +[#1817]: https://github.com/yannickcr/eslint-plugin-react/issues/1817 +[#1815]: https://github.com/yannickcr/eslint-plugin-react/issues/1815 +[#1754]: https://github.com/yannickcr/eslint-plugin-react/issues/1754 +[#1046]: https://github.com/yannickcr/eslint-plugin-react/issues/1046 +[#620]: https://github.com/yannickcr/eslint-plugin-react/pull/620 +[#519]: https://github.com/yannickcr/eslint-plugin-react/issues/519 + ## [7.28.0] - 2021.12.22 ### Added @@ -2176,7 +2276,7 @@ React ([#1073][] @jomasti) * Add support for `PureComponent` in [`prefer-stateless-function`][] ([#781][] @tiemevanveen) ### Fixed -* Fix [`jsx-uses-vars`][] to work better with [`prefer-const`](http://eslint.org/docs/rules/prefer-const). You'll need to upgrade to ESLint 3.4.0 to completely fix the compatibility issue ([#716][]) +* Fix [`jsx-uses-vars`][] to work better with [`prefer-const`](https://eslint.org/docs/rules/prefer-const). You'll need to upgrade to ESLint 3.4.0 to completely fix the compatibility issue ([#716][]) * Fix [`require-render-return`][] crash ([#784][]) * Fix related components detection in [`prop-types`][] ([#735][]) * Fix component detection to ignore functions expression without a parent component @@ -3498,6 +3598,8 @@ If you're still not using React 15 you can keep the old behavior by setting the [`forbid-foreign-prop-types`]: docs/rules/forbid-foreign-prop-types.md [`forbid-prop-types`]: docs/rules/forbid-prop-types.md [`function-component-definition`]: docs/rules/function-component-definition.md +[`hook-use-state`]: docs/rules/hook-use-state.md +[`iframe-missing-sandbox`]: docs/rules/iframe-missing-sandbox.md [`jsx-boolean-value`]: docs/rules/jsx-boolean-value.md [`jsx-child-element-spacing`]: docs/rules/jsx-child-element-spacing.md [`jsx-closing-bracket-location`]: docs/rules/jsx-closing-bracket-location.md @@ -3551,6 +3653,7 @@ If you're still not using React 15 you can keep the old behavior by setting the [`no-did-update-set-state`]: docs/rules/no-did-update-set-state.md [`no-direct-mutation-state`]: docs/rules/no-direct-mutation-state.md [`no-find-dom-node`]: docs/rules/no-find-dom-node.md +[`no-invalid-html-attribute`]: docs/rules/no-invalid-html-attribute.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 @@ -3586,4 +3689,3 @@ If you're still not using React 15 you can keep the old behavior by setting the [`style-prop-object`]: docs/rules/style-prop-object.md [`void-dom-elements-no-children`]: docs/rules/void-dom-elements-no-children.md [`wrap-multilines`]: docs/rules/jsx-wrap-multilines.md -[`no-invalid-html-attribute`]: docs/rules/no-invalid-html-attribute.md diff --git a/README.md b/README.md index b10df85fef..b1efbcd0de 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Use [our preset](#recommended) to get reasonable defaults: ] ``` -If you are using the [new JSX transform from React 17](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#removing-unused-react-imports), extend [`react/jsx-runtime`](https://github.com/yannickcr/eslint-plugin-react/blob/HEAD/index.js#L163-L176) in your eslint config (add `"plugin:react/jsx-runtime"` to `"extends"`) to disable the relevant rules. +If you are using the [new JSX transform from React 17](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#removing-unused-react-imports), extend [`react/jsx-runtime`](https://github.com/yannickcr/eslint-plugin-react/blob/c8917b0885094b5e4cc2a6f613f7fb6f16fe932e/index.js#L163-L176) in your eslint config (add `"plugin:react/jsx-runtime"` to `"extends"`) to disable the relevant rules. You should also specify settings that will be shared across all the plugin rules. ([More about eslint shared settings](https://eslint.org/docs/user-guide/configuring/configuration-files#adding-shared-settings)) @@ -45,8 +45,7 @@ You should also specify settings that will be shared across all the plugin rules "fragment": "Fragment", // Fragment to use (may be a property of ), default to "Fragment" "version": "detect", // React version. "detect" automatically picks the version you have installed. // You can also use `16.0`, `16.3`, etc, if you want to override the detected value. - // default to latest and warns if missing - // It will default to "detect" in the future + // It will default to "latest" and warn if missing, and to "detect" in the future "flowVersion": "0.53" // Flow version }, "propWrapperFunctions": [ @@ -132,6 +131,8 @@ Enable the rules that you would like to use. | | | [react/forbid-foreign-prop-types](docs/rules/forbid-foreign-prop-types.md) | Forbid using another component's propTypes | | | | [react/forbid-prop-types](docs/rules/forbid-prop-types.md) | Forbid certain propTypes | | | đź”§ | [react/function-component-definition](docs/rules/function-component-definition.md) | Standardize the way function component get defined | +| | | [react/hook-use-state](docs/rules/hook-use-state.md) | Ensure symmetric naming of useState hook value and setter variables | +| | | [react/iframe-missing-sandbox](docs/rules/iframe-missing-sandbox.md) | Enforce sandbox attribute on iframe elements | | | | [react/no-access-state-in-setstate](docs/rules/no-access-state-in-setstate.md) | Reports when this.state is accessed within setState | | | | [react/no-adjacent-inline-elements](docs/rules/no-adjacent-inline-elements.md) | Prevent adjacent inline elements not separated by whitespace. | | | | [react/no-array-index-key](docs/rules/no-array-index-key.md) | Prevent usage of Array index in keys | @@ -261,11 +262,11 @@ This pairs well with the `eslint:all` rule. } ``` -**Note**: These configurations will import `eslint-plugin-react` and enable JSX in [parser options](http://eslint.org/docs/user-guide/configuring#specifying-parser-options). +**Note**: These configurations will import `eslint-plugin-react` and enable JSX in [parser options](https://eslint.org/docs/user-guide/configuring/language-options#specifying-parser-options). # License -`eslint-plugin-react` is licensed under the [MIT License](http://www.opensource.org/licenses/mit-license.php). +`eslint-plugin-react` is licensed under the [MIT License](https://opensource.org/licenses/mit-license.php). [npm-url]: https://npmjs.org/package/eslint-plugin-react diff --git a/docs/rules/boolean-prop-naming.md b/docs/rules/boolean-prop-naming.md index b7610b56bf..3c043ca9c0 100644 --- a/docs/rules/boolean-prop-naming.md +++ b/docs/rules/boolean-prop-naming.md @@ -118,5 +118,5 @@ This value is boolean. It tells if nested props should be validated as well. By ``` [PropTypes]: https://reactjs.org/docs/typechecking-with-proptypes.html -[TypeScript]: http://www.typescriptlang.org/ +[TypeScript]: https://www.typescriptlang.org/ [Flow]: https://flow.org/ diff --git a/docs/rules/default-props-match-prop-types.md b/docs/rules/default-props-match-prop-types.md index 35974d6186..4e0b25bd6f 100644 --- a/docs/rules/default-props-match-prop-types.md +++ b/docs/rules/default-props-match-prop-types.md @@ -196,5 +196,5 @@ If you don't care about stray `defaultsProps` in your components, you can disabl - [Official React documentation on defaultProps](https://facebook.github.io/react/docs/typechecking-with-proptypes.html#default-prop-values) [PropTypes]: https://reactjs.org/docs/typechecking-with-proptypes.html -[TypeScript]: http://www.typescriptlang.org/ +[TypeScript]: https://www.typescriptlang.org/ [Flow]: https://flow.org/ diff --git a/docs/rules/display-name.md b/docs/rules/display-name.md index 9c0d911623..cc895ffd7e 100644 --- a/docs/rules/display-name.md +++ b/docs/rules/display-name.md @@ -12,6 +12,14 @@ var Hello = createReactClass({ return
Hello {this.props.name}
; } }); + +const Hello = React.memo(({ a }) => { + return <>{a} +}) + +export default ({ a }) => { + return <>{a} +} ``` Examples of **correct** code for this rule: @@ -23,6 +31,10 @@ var Hello = createReactClass({ return
Hello {this.props.name}
; } }); + +const Hello = React.memo(function Hello({ a }) { + return <>{a} +}) ``` ## Rule Options @@ -37,7 +49,7 @@ var Hello = createReactClass({ When `true` the rule will ignore the name set by the transpiler and require a `displayName` property in this case. -Examples of **correct** code for this rule: +Examples of **correct** code for `{ ignoreTranspilerName: true }` option: ```jsx var Hello = createReactClass({ @@ -66,7 +78,7 @@ export default function Hello({ name }) { Hello.displayName = 'Hello'; ``` -Examples of **incorrect** code for this rule: +Examples of **incorrect** code for `{ ignoreTranspilerName: true }` option: ```jsx var Hello = createReactClass({ diff --git a/docs/rules/forbid-foreign-prop-types.md b/docs/rules/forbid-foreign-prop-types.md index ae8cb5ab0a..64b99f8fc5 100644 --- a/docs/rules/forbid-foreign-prop-types.md +++ b/docs/rules/forbid-foreign-prop-types.md @@ -2,7 +2,7 @@ This rule forbids using another component's prop types unless they are explicitly imported/exported. This allows people who want to use [babel-plugin-transform-react-remove-prop-types](https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types) to remove propTypes from their components in production builds, to do so safely. -In order to ensure that imports are explicitly exported it is recommended to use the ["named" rule in eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/named.md) in conjunction with this rule. +In order to ensure that imports are explicitly exported it is recommended to use the ["named" rule in eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import/blob/HEAD/docs/rules/named.md) in conjunction with this rule. ## Rule Details @@ -25,6 +25,18 @@ Examples of **correct** code for this rule: import SomeComponent, {propTypes as someComponentPropTypes} from './SomeComponent'; ``` +## Rule Options + +```js +... +"react/forbid-foreign-prop-types": [, { "allowInPropTypes": [] }] +... +``` + +### `allowInPropTypes` + +If `true`, the rule will not warn on foreign propTypes usage inside a propTypes declaration. + ## When Not To Use It This rule aims to make a certain production optimization, removing prop types, less prone to error. This rule may not be relevant to you if you do not wish to make use of this optimization. diff --git a/docs/rules/hook-use-state.md b/docs/rules/hook-use-state.md new file mode 100644 index 0000000000..0fb071762f --- /dev/null +++ b/docs/rules/hook-use-state.md @@ -0,0 +1,46 @@ +# Ensure destructuring and symmetric naming of useState hook value and setter variables (react/hook-use-state) + +## Rule Details + +This rule checks whether the value and setter variables destructured from a `React.useState()` call are named symmetrically. + +Examples of **incorrect** code for this rule: + +```js +import React from 'react'; +export default function useColor() { + // useState call is not destructured into value + setter pair + const useStateResult = React.useState(); + return useStateResult; +} +``` + +```js +import React from 'react'; +export default function useColor() { + // useState call is destructured into value + setter pair, but identifier + // names do not follow the [thing, setThing] naming convention + const [color, updateColor] = React.useState(); + return useStateResult; +} +``` + +Examples of **correct** code for this rule: + +```js +import React from 'react'; +export default function useColor() { + // useState call is destructured into value + setter pair whose identifiers + // follow the [thing, setThing] naming convention + const [color, setColor] = React.useState(); + return [color, setColor]; +} +``` + +```js +import React from 'react'; +export default function useColor() { + // useState result is directly returned + return React.useState(); +} +``` diff --git a/docs/rules/iframe-missing-sandbox.md b/docs/rules/iframe-missing-sandbox.md new file mode 100644 index 0000000000..f21f98ad9f --- /dev/null +++ b/docs/rules/iframe-missing-sandbox.md @@ -0,0 +1,40 @@ +# Enforce sandbox attribute on iframe elements (react/iframe-missing-sandbox) + +The sandbox attribute enables an extra set of restrictions for the content in the iframe. Using sandbox attribute is considered a good security practice. + +See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox + +## Rule Details + +This rule checks all React iframe elements and verifies that there is sandbox attribute and that it's value is valid. In addition to that it also reports cases where attribute contains `allow-scripts` and `allow-same-origin` at the same time as this combination allows the embedded document to remove the sandbox attribute and bypass the restrictions. + +The following patterns are considered warnings: + +```jsx +var React = require('react'); + +var Frame = () => ( +
+ + {React.createElement('iframe')} +
+); +``` + +The following patterns are **not** considered warnings: + +```jsx +var React = require('react'); + +var Frame =