File tree Expand file tree Collapse file tree
react-dom-bindings/src/client Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -292,7 +292,7 @@ export function initInput(
292292 typeof checkedOrDefault !== 'symbol' &&
293293 ! ! checkedOrDefault ;
294294
295- if ( isHydrating ) {
295+ if ( isHydrating && checked == null ) {
296296 // Detach .checked from .defaultChecked but leave user input alone
297297 node . checked = node . checked ;
298298 } else {
Original file line number Diff line number Diff line change @@ -1300,23 +1300,22 @@ describe('ReactDOMInput', () => {
13001300
13011301 // Currently, we don't fire onChange when hydrating
13021302 assertLog ( [ ] ) ;
1303- // Strangely, we leave `b` checked even though we rendered A with
1304- // checked={true} and B with checked={false}. Arguably this is a bug.
1305- expect ( a . checked ) . toBe ( false ) ;
1306- expect ( b . checked ) . toBe ( true ) ;
1303+ // Instead, we reset the form to match React state and you lose the user's input.
1304+ expect ( a . checked ) . toBe ( true ) ;
1305+ expect ( b . checked ) . toBe ( false ) ;
13071306 expect ( c . checked ) . toBe ( false ) ;
13081307 expect ( isCheckedDirty ( a ) ) . toBe ( true ) ;
13091308 expect ( isCheckedDirty ( b ) ) . toBe ( true ) ;
13101309 expect ( isCheckedDirty ( c ) ) . toBe ( true ) ;
13111310 assertInputTrackingIsCurrent ( container ) ;
13121311
1313- // If we click on C now though ...
1312+ // If we click on C now...
13141313 await act ( async ( ) => {
13151314 setUntrackedChecked . call ( c , true ) ;
13161315 dispatchEventOnNode ( c , 'click' ) ;
13171316 } ) ;
13181317
1319- // then since C 's onClick doesn't set state, A becomes rechecked .
1318+ // there 's no change .
13201319 assertLog ( [ 'click c' ] ) ;
13211320 expect ( a . checked ) . toBe ( true ) ;
13221321 expect ( b . checked ) . toBe ( false ) ;
You can’t perform that action at this time.
0 commit comments