Build1 distinct publisher3 min readUpdated
Nobody filed an issue. The forked diff named an API gap that sat unfixed upstream for four years, and the fix finally shipped in 1.1.0.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
The fork did not describe a problem, it published the call signature it wanted. Its example passed `currentPage`, `isExpansion`, `onTryMoveNextPage` and `onChangedCurrentPage` [8]. The upstream component accepted `initialCurrentPage`, `initialIsExpansion` and `onChangeCurrentPage` [9]. That prefix is the whole disagreement, and the maintainer says as much: `initial` means the component takes a starting page and then never lets the caller touch it again [20][10].
Ownership decides what the host app can build. A parent that cannot set the page cannot jump to it from a table of contents or keep it in the URL, and it cannot refuse the move when the next chapter has to be bought first [11].
The retrofit has two traps worth copying. The `onChange` call belongs inside the setter, not in an effect watching the value, because in controlled mode the local value never changes, so the effect never fires and the parent hears nothing [13]. The setter also needs the current value and the current callback held in refs, or every render hands out a new setter and everything downstream re-renders with it [12].
The harder question is what happens to state the component writes for itself. Going fullscreen forces the expanded view and restores the previous value on exit; switching to a two-page spread rounds the current page down to an even number [14]. Under controlled props neither can simply happen. The resolution is the one a controlled text input already uses: the component asks through `onChange`, and if the parent ignores it, nothing moves [15].
Read as a report, the fork's commit log arrives pre-triaged. Of four visible changes, two match fixes the maintainer made anyway, one of them about a year later [6][7][19]. The remaining one, the controlled example, is the item he did not get to for four years [7]. The arithmetic is unkind. The oldest fork appeared about three months after first publication and ran for nearly a year [4], so `controlled.tsx` existed no later than fifteen months in, leaving a minimum of thirty-three months between a working sketch of the API and 1.1.0 shipping it [18].
None of this required the fork authors to cooperate, and they did not: no issue, no pull request [3]. It required only that the fork be findable, which it was, since it carried the upstream description and repository URL under a near-identical name and turned up while the maintainer was browsing npm [2], and that it be alive, which its version number showed at 0.6.3 against upstream's 0.3.5 [5]. Version 1.1.0 now takes `currentPage` and `isExpansion` as optional independent props [16] and adds `onTryMoveNextPage` and `onTryMovePrevPage`, which fire before the page changes [17]. That last pair is the paywall hook, and its name came from someone who never said a word [8].
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
The author maintains react-comic-viewer, a small comic and manga viewer component for React.
While browsing npm the author found three packages published by other people under basically his package's name; all three were forks of his, with the same description and the same repository URL pointing back at his repo.
None of the three fork authors had ever opened an issue or a pull request on the upstream project.
The oldest fork was created about three months after the author first published the package, and it kept going for almost a year.
At the time, the fork's version number ran ahead of upstream: the fork was on 0.6.3 while the author was on 0.3.5.
The fork's commit messages were 'remove sass', 'fix: support className props' and 'use Hotkeys', plus a new example file called controlled.tsx.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Detailed but single-sourced and self-reported
The source is technically specific and internally consistent: it quotes the fork's commit messages, shows both prop shapes, and includes the full useControllableState implementation with reasoning. But everything rests on one first-person account from the maintainer, no fork package names, URLs, or registry records are cited, and no independent source in the cluster corroborates the timeline, version numbers, or the claim that the forks were reactions to the API gap.
One small library, no usage figures
Concrete adoption signals exist but are thin: a shipped 1.1.0 release with the new controlled API, and three third-party forks republished on npm, one of which had advanced to 0.6.3 while upstream sat at 0.3.5, implying at least some downstream use. There are no download counts, dependent projects, or named adopters for upstream or the forks, and no evidence anyone has consumed the 1.1.0 controlled props.
Mildly overstated by the framing, sober in the body
The narrative framing — forks as the best bug report the project ever got — is rhetorical and asserts intent the source cannot establish, since no fork author ever contacted upstream and none are identified. Offsetting that, the body is unusually self-critical and scoped: the author calls the controlled/uncontrolled pattern unremarkable, admits four years of inaction, and makes no claims about downloads, users, or importance beyond his own package. Net overstatement is small.
Maintainer promoting his own release
The author is the maintainer of the package under discussion, announces his own 1.1.0 release in the post, and links a hosted demo, so there is a clear promotional interest in the framing that forks validated his API redesign. The incentive is disclosed rather than hidden — first-person throughout, with candid admission of a four-year delay — and the post is on a developer publishing platform with no visible commercial sponsorship in the cluster.
Plausible and specific, but unverifiable
Confidence is limited by structure rather than plausibility. The technical content is checkable and the account is coherent, so the API problem and the 1.1.0 fix are likely accurate. The causal story — that the forks were driven by the initial-prefix limitation — and the fork details themselves depend entirely on one interested self-report with no named artifacts and no second publisher in the cluster.
build
Chess's one-game-a-day cap is a two-core bill, and WebAssembly moves it onto your laptop1 distinct publisher
build
A missing package.json line broke every pnpm user of a React dashboard template1 distinct publisher
build
752 Nigerian institutions, shipped as a repo instead of an endpoint1 distinct publisher
build
The Escape-key listener you cannot fix with a dependency array1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 22, 2026