feat(lint): integrate eslint-plugin-react-hooks with rules-of-hooks and exhaustive-deps as errors#10809
Open
mmorel-35 wants to merge 1 commit intoswagger-api:masterfrom
Open
feat(lint): integrate eslint-plugin-react-hooks with rules-of-hooks and exhaustive-deps as errors#10809mmorel-35 wants to merge 1 commit intoswagger-api:masterfrom
mmorel-35 wants to merge 1 commit intoswagger-api:masterfrom
Conversation
…nd exhaustive-deps as errors Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
3a5540a to
6eb087d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
eslint-plugin-react-hooks@7.0.1and enforces bothrules-of-hooksandexhaustive-depsas errors across the entire codebase, eliminating pre-existing hook violations before activating the rules.ESLint configuration
react-hooksplugin to.eslintrc.jswith both rules at error level (2)plugin:react-hooks/recommended— v7 bundles additional rules (refs,static-components,set-state-in-effect) incompatible with the codebase's plugin-system patternsPhase 1 —
rules-of-hooksfixesPre-existing violations corrected before enabling the rule:
hooks.js(useRenderedSchemas)useContextcalled inside anifbranch — hook order not guaranteed$-prefixed keyword componentsThe
useRenderedSchemasfix is the most impactful: a conditionaluseContextcan silently cause diverging hook call order between renders.All nine
$-prefixed keyword component function names have been renamed to PascalCase for consistency and correctrules-of-hooksanalysis:$defs.jsx$defsDefsKeywordDefs$vocabulary.jsx$vocabularyVocabularyKeywordVocabulary$ref.jsx$refRefKeywordRef$dynamicRef.jsx$dynamicRefDynamicRefKeywordDynamicRef$schema.jsx$schemaSchemaKeywordSchema$anchor.jsx$anchorAnchorKeywordAnchor$id.jsx$idIdKeywordId$dynamicAnchor.jsx$dynamicAnchorDynamicAnchorKeywordDynamicAnchor$comment.jsx$commentCommentKeywordCommentAll renames are fully propagated to consuming files (
hoc.jsx,index.js,JSONSchema.jsx): import aliases, local variable names, and JSX element names. Component registration/lookup string keys (e.g."Keyword$ref","JSONSchema202012Keyword$ref") are preserved for backward compatibility.Phase 2+3 —
exhaustive-depsfixes and suppressionsEach violation resolved either by correcting deps or suppressing with a documented comment:
servers.jsx— seconduseEffectgets missing Redux action deps (setSelectedServer,setServerVariableValue); mount-only first effect suppressedmodels.jsx—schemasPathhoisted asObject.freeze(["components", "schemas"])module constant; missinglayoutActions/schemasPathadded to bothuseCallbackdeps;useEffectsuppressed (intentionally watches onlyisOpen/defaultModelsExpandDepthto avoid over-firing)hooks.js(useIsExpanded) —useEffectand twouseCallbacks suppressed:pathMutatoris recreated every render; including it would cause infinite update loops or defeat the purpose ofuseCallbackmodel-example.jsx—tabs.exampleadded touseEffectdep array (trivial:tabsis stable viauseMemo([], []))flavors/swagger-ui-react/index.jsx— three effects suppressed: mount-only SwaggerUI initializer, and two effects usingusePreviousvalues where adding those deps would cause double-firingMotivation and Context
eslint-plugin-react-hookscatches two categories of bugs:rules-of-hooks: hooks called conditionally or outside components/hooks → unpredictable render behaviorexhaustive-deps: stale closures in effects/callbacks → subtle data staleness bugs that are hard to reproduceThe
useRenderedSchemasviolation was a real latent bug. Renaming all$-prefixed component functions to PascalCase is required for the rule to correctly analyze hook calls inside those components, and ensures consistent naming across the entire keyword component set.How Has This Been Tested?
npm run lint-errors(used in CI) passes with zero errors. All 829 existing unit tests pass.Screenshots (if appropriate):
N/A
Checklist
My PR contains...
src/is unmodified: changes to documentation, CI, metadata, etc.)package.json)My changes...
Documentation
Automated tests