Controlled checkbox reverts when another state update happens during the click

オープン
#127 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
18/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
react, typescript
領域
frontend

調査の方向性

The payload names no source files, so start from the reproduction: a controlled input type="checkbox" inside a label, with a document-level click listener that calls setState. Run that snippet in Chromium and confirm the box reverts on the first click. Then trace how a state update flushed in a microtask before change re-applies the old checked value. Done means the box stays checked after onChange runs, and the case is covered by a test alongside the behaviour from #116. Coordinate with #116 before starting, since it touches the same code.

索引モデルが issue の本文から書いたものです。

説明

A controlled checkbox can’t be checked when something else updates state from a native click listener, e.g. a click-away listener like the one in MUI’s Snackbar. Redact flushes that update in a microtask before the browser fires change, re-renders the checkbox with the old checked and writes it back to the DOM. The change event then reports the old value, so onChange keeps the box unchecked.

Reproduction
import {useEffect, useState} from 'react'
import {createRoot} from 'react-dom/client'

const App = () => {
  const [clicks, setClicks] = useState(0)
  const [checked, setChecked] = useState(false)

  useEffect(() => {
    const onClick = () => setClicks((n) => n + 1)
    document.addEventListener('click', onClick)
    return () => document.removeEventListener('click', onClick)
  }, [])

  return (
    <label>
      <input
        type="checkbox"
        checked={checked}
        onChange={(e) => setChecked(e.target.checked)}
      />
      Checked: {String(checked)}, document clicks: {clicks}
    </label>
  )
}

createRoot(document.getElementById('root')).render(<App />)

Click the checkbox:

React DOM 19.2.7 Redact 0.2.3
After the 1st click Checked: true Checked: false
After the 2nd click Checked: false Checked: false

On Redact the box never stays checked. Tested in Chromium with Vite and the default redact() plugin.

Expected

As in React DOM, the checkbox keeps the value the browser toggled until change has fired. #116 touches the same code (restoring controlled state after change), but this case calls setState and fails before onChange runs.

主要言語
TypeScript
スター
537
フォーク
22
平均マージ
11時間 37分
マージ済み PR(30日)
35

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

TanStack/redact のほかの issue

TanStack/redact の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。