Skip to content

Updated the client and examples release groups to use eslint-config-fluid v13.0#27530

Open
TommyBrosman wants to merge 6 commits into
microsoft:mainfrom
TommyBrosman:tbrosman/eslint-config-13
Open

Updated the client and examples release groups to use eslint-config-fluid v13.0#27530
TommyBrosman wants to merge 6 commits into
microsoft:mainfrom
TommyBrosman:tbrosman/eslint-config-13

Conversation

@TommyBrosman

@TommyBrosman TommyBrosman commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Description

Updates the client release group to use @fluidframework/eslint-config-fluid v13 (from v9) and fixes all lint errors the new config surfaces.

Because the client and examples release groups share a single pnpm catalog entry for eslint-config-fluid, bumping the catalog applies v13 to both groups. This PR therefore also fixes lint errors in the examples, not just the client release group.

Lint fixes

  • no-only-tests — added targeted suppressions where .only is selected by test data/options rather than committed accidentally (merge-tree, container-runtime, local-server-stress-tests, map).
  • no-restricted-syntax — import the TypeBox Type namespace via import * as Type from "@sinclair/typebox" instead of the named value export, which defeats tree-shaking (tree-cli-app).
  • @eslint-react/no-create-ref — use useRef(null) instead of createRef() in a function component (triangle-view). The original allocated a new ref object every render.
  • @eslint-react/no-useless-fragment — return null instead of an empty fragment (data-object-grid).
  • @eslint-react/dom/no-render — migrate ReactDOM.render to createRoot().render() (shared-tree-demo, app-insights-logger, view-framework-sampler, devtools-test-app).
  • Repaired the text-editor and inventory-app eslint configs, which referenced the removed classic react plugin (v13 replaced it with @eslint-react), re-expressing the intended rules via @eslint-react / react-hooks.

Notable behavioral details

  • Render-callback timing: ReactDOM.render's third callback argument has no equivalent on createRoot().render(). Where the callback mattered, the side effect was moved into a useLayoutEffect (runs after DOM commit, before paint) rather than firing before the commit. flushSync is not an option (@eslint-react/dom/no-flush-sync is an error).
  • devtools-test-app StrictMode removal: this app creates a singleton Devtools instance and disposes it in an effect cleanup. The original wrapped the app in <StrictMode> while rendering via the legacy ReactDOM.render API. React 18's StrictMode setup→cleanup→setup effect double-invoke only runs under createRoot; under legacy ReactDOM.render the tree stays in React-17 mode, so that check never fired and the wrapper was inert for effects. Migrating to createRoot activated the double-invoke, which disposed the singleton on the simulated unmount and left later renders using a disposed instance (The devtools instance has been disposed). The app is not resilient to that remount cycle, so <StrictMode> was removed to preserve the app's actual prior behavior; making it StrictMode-safe would be a larger refactor out of scope here.

Reviewer Guidance

  • This is a tooling/lint-config change. No production/public API surface is modified — changes are limited to example apps, test files, and eslint configs.
  • All affected example apps were run manually and verified working: data-object-grid, tree-cli-app, triangle-view (via the multiview container), app-insights-logger, shared-tree-demo, view-framework-sampler, devtools-test-app, text-editor, inventory-app.
    • Caveat: shared-tree-demo was verified without a real SPE_CLIENT_ID (the changed create-new render path does not depend on SPE).
  • The text-editor / inventory-app config changes drop three classic stylistic react/* rules (jsx-boolean-value, jsx-fragments, self-closing-comp) that have no @eslint-react equivalent. Flag if you'd prefer those preserved another way.

- Removed the no-restricted-syntax block from tree (now in the base config).
- Added an ESLint suppression in one test.
@TommyBrosman TommyBrosman requested a review from a team as a code owner June 10, 2026 19:48
Copilot AI review requested due to automatic review settings June 10, 2026 19:48
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Hi! Thank you for opening this PR. Want me to review it?

Based on the diff (1201 lines, 27 files), I've queued these reviewers:

  • Correctness — logic errors, race conditions, lifecycle issues
  • Security — vulnerabilities, secret exposure, injection
  • API Compatibility — breaking changes, release tags, type design
  • Performance — algorithmic regressions, memory leaks
  • Testing — coverage gaps, hollow tests

How this works

  • Adjust the reviewer set by ticking/unticking boxes above. Reviewer toggles alone don't trigger anything.

  • Tick Start review below to dispatch the review fleet.

  • After review finishes, tick Start review again to request another run — it auto-resets after each dispatch.

  • This comment updates as new commits land; your reviewer selections are preserved.

  • Start review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 3 out of 4 changed files in this pull request and generated no comments.

@TommyBrosman TommyBrosman marked this pull request as draft June 10, 2026 20:01
v13.0.0 is now past the minimumReleaseAge window, so the temporary minimumReleaseAgeExclude entry is no longer needed. Regenerated the lockfile without the override.
Bumping the eslint-config-fluid catalog entry to v13 applied the new config to both the client and examples release groups (they share the pnpm catalog), surfacing new lint errors. This fixes them:

- no-only-tests: added targeted suppressions where .only is driven by test data/options (merge-tree, container-runtime, local-server-stress-tests, map).
- no-restricted-syntax: import the TypeBox Type namespace via 'import * as Type' instead of the named value export (tree-cli-app).
- @eslint-react/no-create-ref: use useRef(null) instead of createRef() in a function component (triangle-view). createRef allocated a new ref every render.
- @eslint-react/no-useless-fragment: return null instead of an empty fragment (data-object-grid).
- @eslint-react/dom/no-render: migrate ReactDOM.render to createRoot().render() (shared-tree-demo, app-insights-logger, view-framework-sampler, devtools-test-app).
- Repaired text-editor and inventory-app eslint configs that referenced the removed classic 'react' plugin, re-expressing the intended rules via @eslint-react / react-hooks.

Render-callback timing: ReactDOM.render's third callback argument does not exist on createRoot().render(). Where that callback mattered, the side effect was moved into a useLayoutEffect (runs after DOM commit, before paint) rather than firing it before the commit. flushSync is not an option (@eslint-react/dom/no-flush-sync is an error).

devtools-test-app StrictMode removal: this app initializes a singleton Devtools instance and disposes it in an effect cleanup. The original code wrapped the app in <StrictMode> while rendering via the legacy ReactDOM.render API. React 18's StrictMode setup->cleanup->setup effect double-invocation only runs under the new createRoot path; under legacy ReactDOM.render the tree stays in React-17 mode, so that check never fired and the wrapper was effectively inert for effects. Migrating to createRoot activated the double-invoke, which disposed the singleton on the simulated unmount and left later renders using a disposed instance ('The devtools instance has been disposed'). The app is not resilient to that remount cycle, so StrictMode was removed to preserve the app's actual prior behavior; making it StrictMode-safe would be a larger refactor out of scope for this change.
@TommyBrosman TommyBrosman changed the title Updated the client release group to use eslint-config-fluid v13.0 Updated the client and examples release groups to use eslint-config-fluid v13.0 Jun 12, 2026
@TommyBrosman TommyBrosman marked this pull request as ready for review June 12, 2026 20:35
@TommyBrosman TommyBrosman requested review from a team as code owners June 12, 2026 20:35

@alexvy86 alexvy86 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving for devtools, but LGTM overall

Comment thread examples/apps/data-object-grid/src/dataObjectGridView.tsx Outdated

@CraigMacomber CraigMacomber left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert on the react code being impacted, but everything else looks good, and the react stuff seems potentially reasonable, but I'll leave its review to others.

Comment thread examples/apps/data-object-grid/src/dataObjectGridView.tsx Outdated
Comment thread examples/data-objects/inventory-app/eslint.config.mts Outdated
…ols-view

Address @eslint-react and unicorn rule violations surfaced by the v13 config:

- blobs, devtools-view: return idiomatic null for empty render output and
  disable unicorn/no-null at the package level (matching data-object-grid).
- example-utils, external-data: migrate deprecated ReactDOM.render to
  createRoot().render() and allow the react-dom/client subpath import.
- devtools-view: hoist nested Recharts tick components (CustomizedXAxisTick/
  CustomizedYAxisTick) to top level to satisfy
  @eslint-react/no-nested-component-definitions, and return ReactNode from
  TreeDataView so null is permitted without @rushstack/no-new-null.
- data-object-grid: minor comment wording tweak.
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.

5 participants