Skip to content

chore: add ESLint with react-hooks - #60

Merged
ivoIturrieta merged 1 commit into
unlayer:mainfrom
sidgaikwad:chore/eslint
Sep 8, 2026
Merged

chore: add ESLint with react-hooks#60
ivoIturrieta merged 1 commit into
unlayer:mainfrom
sidgaikwad:chore/eslint

Conversation

@sidgaikwad

Copy link
Copy Markdown
Contributor

Fixes #38.

npm run lint was prettier --check . — formatting only, no static analysis anywhere in the repo or CI.

Why this one matters here

ImageEditor.tsx deliberately runs hand-tuned effect dependency arrays, reading current values through latestPropsRef rather than listing them as deps. Correct by design — the whole serialized-chain architecture depends on not remounting when those change — but nothing recorded that at the call site, and nothing would catch a future accidental omission.

What ESLint found

Enabling it surfaced exactly two things, both real, and nothing else:

1. react-hooks/exhaustive-deps on the updatable-options effect — the case the issue predicted. It legitimately omits theme/locale/translations because updatableKey is already a stable digest of them; listing them too would re-run the effect on every unrelated identity change of translations without changing what gets applied. Now carries an explicit eslint-disable-next-line with that reason written down.

2. @typescript-eslint/no-unused-vars on a rest-destructure in the testsconst { container, image, ...passedThrough } = received is the idiomatic way to omit keys; the named bindings are the point. Fixed with ignoreRestSiblings: true, a config setting rather than a code change.

Set to error, not warn

exhaustive-deps defaults to a warning. I set it to error so omitting a dependency requires a written justification rather than passing silently — which is the entire value of adding it to this codebase.

Proof it's live — I removed image from a dep array that genuinely needs it:

177:6  error  React Hook useEffect has a missing dependency: 'image'  react-hooks/exhaustive-deps

Notes

  • Config is eslint.config.mjs, not .js — the package is "type": "commonjs".
  • eslint-config-prettier is last, so ESLint and Prettier can't fight.
  • lint is now eslint . && prettier --check ., so CI picks it up with no workflow change.
  • Scoped to src/, test/ and configs; demo/ can follow separately.
  • no-console is configured to match the CONTRIBUTING rule (allows info/warn/error).

Lint, typecheck, tests (50, 100% coverage) and build all clean.

`npm run lint` was `prettier --check .` — formatting only, no static
analysis at all.

That matters here specifically because ImageEditor.tsx runs hand-tuned
effect dependency arrays and reads current values through latestPropsRef
instead of listing them as deps. Those are correct by design, but nothing
recorded that or would catch a future accidental omission.

Flat config with typescript-eslint, eslint-plugin-react-hooks and
eslint-config-prettier. Two findings, both real:

- The updatable-options effect legitimately omits theme/locale/translations
  because updatableKey is already a digest of them. Now carries an explicit
  disable with the reason written down.
- A rest-destructure in the tests tripped no-unused-vars; ignoreRestSiblings
  is the idiomatic setting for omit-by-destructuring.

exhaustive-deps is set to error rather than warn, so omitting a dependency
requires a written justification instead of passing silently.
@vercel

vercel Bot commented Sep 4, 2026

Copy link
Copy Markdown

@sidgaikwad is attempting to deploy a commit to the Unlayer Team on Vercel.

A member of the Team first needs to authorize it.

@ivoIturrieta
ivoIturrieta merged commit 100b92c into unlayer:main Sep 8, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add ESLint + eslint-plugin-react-hooks (lint is Prettier-only today)

2 participants