client: clear the four lint warnings and make warnings fail CI #5

Closed
opened 2026-10-10 14:08:07 +09:00 by bot-genji1024 · 0 comments
Collaborator

npm run lint reports four warnings and no errors. CI (#2) passes on warnings, so new ones can creep in unnoticed. Clear them, then make warnings fail.

The warnings and the plan

react(set-state-in-effect) — components/ImagePicker.tsx:14, pages/Profile.tsx:29

Both components make object URLs for image previews in an effect and put them in state, revoking them on cleanup. That is the right pattern here: an object URL is an external resource whose lifetime must follow the component, which is exactly what effects are for. Moving the creation into useMemo would break under StrictMode, whose double effect run revokes URLs that a cached memo will not recreate.

Plan: extract the pattern into one hook, useObjectUrls(blobs) (in src/hooks/), used by both components. Allow the rule inside that hook only, with a comment saying why. The exception lives in one documented place instead of two.

react(only-export-components) — pages/Diary.tsx:56

postWithImages (upload the picked images, then post the entry) is exported from the page component's file and imported by pages/Notes.tsx. That breaks fast refresh for the file, and it is data-layer code anyway.

Plan: move it to src/matrix/diary.ts, next to uploadImage and postEntry, which it calls; update both imports.

eslint(no-unused-vars) — matrix/koto.test.ts:3

beforeAll is imported but unused. Plan: remove it.

Make warnings fail

Change the lint script to oxlint --deny-warnings, so a local npm run lint and CI agree.

Verification

  • npm run lint reports nothing and exits 0; adding a warning makes it exit non-zero
  • typecheck, unit tests and build pass (CI)
  • On the demo after merging: image previews still show and disappear correctly when posting in the diary and notes, and when changing the profile picture
`npm run lint` reports four warnings and no errors. CI (#2) passes on warnings, so new ones can creep in unnoticed. Clear them, then make warnings fail. ## The warnings and the plan ### `react(set-state-in-effect)` — `components/ImagePicker.tsx:14`, `pages/Profile.tsx:29` Both components make object URLs for image previews in an effect and put them in state, revoking them on cleanup. That is the right pattern here: an object URL is an external resource whose lifetime must follow the component, which is exactly what effects are for. Moving the creation into `useMemo` would break under StrictMode, whose double effect run revokes URLs that a cached memo will not recreate. Plan: extract the pattern into one hook, `useObjectUrls(blobs)` (in `src/hooks/`), used by both components. Allow the rule inside that hook only, with a comment saying why. The exception lives in one documented place instead of two. ### `react(only-export-components)` — `pages/Diary.tsx:56` `postWithImages` (upload the picked images, then post the entry) is exported from the page component's file and imported by `pages/Notes.tsx`. That breaks fast refresh for the file, and it is data-layer code anyway. Plan: move it to `src/matrix/diary.ts`, next to `uploadImage` and `postEntry`, which it calls; update both imports. ### `eslint(no-unused-vars)` — `matrix/koto.test.ts:3` `beforeAll` is imported but unused. Plan: remove it. ## Make warnings fail Change the `lint` script to `oxlint --deny-warnings`, so a local `npm run lint` and CI agree. ## Verification - `npm run lint` reports nothing and exits 0; adding a warning makes it exit non-zero - typecheck, unit tests and build pass (CI) - On the demo after merging: image previews still show and disappear correctly when posting in the diary and notes, and when changing the profile picture
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
genji1024/koto#5
No description provided.