@@ -52,14 +52,12 @@ import {hasRole} from './DOMAccessibilityRoles';
52
52
import {
53
53
setInitialProperties ,
54
54
updateProperties ,
55
+ hydrateProperties ,
56
+ hydrateText ,
55
57
diffHydratedProperties ,
58
+ getPropsFromElement ,
56
59
diffHydratedText ,
57
60
trapClickOnNonInteractiveElement ,
58
- checkForUnmatchedText ,
59
- warnForDeletedHydratableElement ,
60
- warnForDeletedHydratableText ,
61
- warnForInsertedHydratedElement ,
62
- warnForInsertedHydratedText ,
63
61
} from './ReactDOMComponent' ;
64
62
import { getSelectionInformation , restoreSelection } from './ReactInputSelection' ;
65
63
import setTextContent from './setTextContent' ;
@@ -1342,6 +1340,26 @@ export function getFirstHydratableChildWithinSuspenseInstance(
1342
1340
return getNextHydratable ( parentInstance . nextSibling ) ;
1343
1341
}
1344
1342
1343
+ export function describeHydratableInstanceForDevWarnings (
1344
+ instance : HydratableInstance ,
1345
+ ) : string | { type : string , props : $ReadOnly < Props > } {
1346
+ // Reverse engineer a pseudo react-element from hydratable instnace
1347
+ if ( instance . nodeType === ELEMENT_NODE ) {
1348
+ // Reverse engineer a set of props that can print for dev warnings
1349
+ return {
1350
+ type : instance . nodeName . toLowerCase ( ) ,
1351
+ props : getPropsFromElement ( ( instance : any ) ) ,
1352
+ } ;
1353
+ } else if ( instance . nodeType === COMMENT_NODE ) {
1354
+ return {
1355
+ type : 'Suspense' ,
1356
+ props : { } ,
1357
+ } ;
1358
+ } else {
1359
+ return instance . nodeValue ;
1360
+ }
1361
+ }
1362
+
1345
1363
export function validateHydratableInstance (
1346
1364
type : string ,
1347
1365
props : Props ,
@@ -1361,14 +1379,23 @@ export function hydrateInstance(
1361
1379
props : Props ,
1362
1380
hostContext : HostContext ,
1363
1381
internalInstanceHandle : Object ,
1364
- shouldWarnDev : boolean ,
1365
- ) : void {
1382
+ ) : boolean {
1366
1383
precacheFiberNode ( internalInstanceHandle , instance ) ;
1367
1384
// TODO: Possibly defer this until the commit phase where all the events
1368
1385
// get attached.
1369
1386
updateFiberProps ( instance , props ) ;
1370
1387
1371
- diffHydratedProperties ( instance , type , props , shouldWarnDev , hostContext ) ;
1388
+ return hydrateProperties ( instance , type , props , hostContext ) ;
1389
+ }
1390
+
1391
+ // Returns a Map of properties that were different on the server.
1392
+ export function diffHydratedPropsForDevWarnings (
1393
+ instance : Instance ,
1394
+ type : string ,
1395
+ props : Props ,
1396
+ hostContext : HostContext ,
1397
+ ) : null | $ReadOnly < Props > {
1398
+ return diffHydratedProperties ( instance , type , props , hostContext ) ;
1372
1399
}
1373
1400
1374
1401
export function validateHydratableTextInstance (
@@ -1389,11 +1416,26 @@ export function hydrateTextInstance(
1389
1416
textInstance : TextInstance ,
1390
1417
text : string ,
1391
1418
internalInstanceHandle : Object ,
1392
- shouldWarnDev : boolean ,
1419
+ parentInstanceProps : null | Props ,
1393
1420
) : boolean {
1394
1421
precacheFiberNode ( internalInstanceHandle , textInstance ) ;
1395
1422
1396
- return diffHydratedText ( textInstance , text ) ;
1423
+ return hydrateText ( textInstance , text , parentInstanceProps ) ;
1424
+ }
1425
+
1426
+ // Returns the server text if it differs from the client.
1427
+ export function diffHydratedTextForDevWarnings (
1428
+ textInstance : TextInstance ,
1429
+ text : string ,
1430
+ parentProps : null | Props ,
1431
+ ) : null | string {
1432
+ if (
1433
+ parentProps === null ||
1434
+ parentProps [ SUPPRESS_HYDRATION_WARNING ] !== true
1435
+ ) {
1436
+ return diffHydratedText ( textInstance , text ) ;
1437
+ }
1438
+ return null ;
1397
1439
}
1398
1440
1399
1441
export function hydrateSuspenseInstance (
@@ -1485,183 +1527,6 @@ export function shouldDeleteUnhydratedTailInstances(
1485
1527
return parentType !== 'form' && parentType !== 'button' ;
1486
1528
}
1487
1529
1488
- export function didNotMatchHydratedContainerTextInstance (
1489
- parentContainer : Container ,
1490
- textInstance : TextInstance ,
1491
- text : string ,
1492
- shouldWarnDev : boolean ,
1493
- ) {
1494
- checkForUnmatchedText ( textInstance . nodeValue , text , shouldWarnDev ) ;
1495
- }
1496
-
1497
- export function didNotMatchHydratedTextInstance (
1498
- parentType : string ,
1499
- parentProps : Props ,
1500
- parentInstance : Instance ,
1501
- textInstance : TextInstance ,
1502
- text : string ,
1503
- shouldWarnDev : boolean ,
1504
- ) {
1505
- if ( parentProps [ SUPPRESS_HYDRATION_WARNING ] !== true ) {
1506
- checkForUnmatchedText ( textInstance . nodeValue , text , shouldWarnDev ) ;
1507
- }
1508
- }
1509
-
1510
- export function didNotHydrateInstanceWithinContainer (
1511
- parentContainer : Container ,
1512
- instance : HydratableInstance ,
1513
- ) {
1514
- if ( __DEV__ ) {
1515
- if ( instance . nodeType === ELEMENT_NODE ) {
1516
- warnForDeletedHydratableElement ( parentContainer , ( instance : any ) ) ;
1517
- } else if ( instance . nodeType === COMMENT_NODE ) {
1518
- // TODO: warnForDeletedHydratableSuspenseBoundary
1519
- } else {
1520
- warnForDeletedHydratableText ( parentContainer , ( instance : any ) ) ;
1521
- }
1522
- }
1523
- }
1524
-
1525
- export function didNotHydrateInstanceWithinSuspenseInstance (
1526
- parentInstance : SuspenseInstance ,
1527
- instance : HydratableInstance ,
1528
- ) {
1529
- if ( __DEV__ ) {
1530
- // $FlowFixMe[incompatible-type]: Only Element or Document can be parent nodes.
1531
- const parentNode : Element | Document | null = parentInstance . parentNode ;
1532
- if ( parentNode !== null ) {
1533
- if ( instance . nodeType === ELEMENT_NODE ) {
1534
- warnForDeletedHydratableElement ( parentNode , ( instance : any ) ) ;
1535
- } else if ( instance . nodeType === COMMENT_NODE ) {
1536
- // TODO: warnForDeletedHydratableSuspenseBoundary
1537
- } else {
1538
- warnForDeletedHydratableText ( parentNode , ( instance : any ) ) ;
1539
- }
1540
- }
1541
- }
1542
- }
1543
-
1544
- export function didNotHydrateInstance (
1545
- parentType : string ,
1546
- parentProps : Props ,
1547
- parentInstance : Instance ,
1548
- instance : HydratableInstance ,
1549
- ) {
1550
- if ( __DEV__ ) {
1551
- if ( instance . nodeType === ELEMENT_NODE ) {
1552
- warnForDeletedHydratableElement ( parentInstance , ( instance : any ) ) ;
1553
- } else if ( instance . nodeType === COMMENT_NODE ) {
1554
- // TODO: warnForDeletedHydratableSuspenseBoundary
1555
- } else {
1556
- warnForDeletedHydratableText ( parentInstance , ( instance : any ) ) ;
1557
- }
1558
- }
1559
- }
1560
-
1561
- export function didNotFindHydratableInstanceWithinContainer (
1562
- parentContainer : Container ,
1563
- type : string ,
1564
- props : Props ,
1565
- ) {
1566
- if ( __DEV__ ) {
1567
- warnForInsertedHydratedElement ( parentContainer , type , props ) ;
1568
- }
1569
- }
1570
-
1571
- export function didNotFindHydratableTextInstanceWithinContainer (
1572
- parentContainer : Container ,
1573
- text : string ,
1574
- ) {
1575
- if ( __DEV__ ) {
1576
- warnForInsertedHydratedText ( parentContainer , text ) ;
1577
- }
1578
- }
1579
-
1580
- export function didNotFindHydratableSuspenseInstanceWithinContainer (
1581
- parentContainer : Container ,
1582
- ) {
1583
- if ( __DEV__ ) {
1584
- // TODO: warnForInsertedHydratedSuspense(parentContainer);
1585
- }
1586
- }
1587
-
1588
- export function didNotFindHydratableInstanceWithinSuspenseInstance (
1589
- parentInstance : SuspenseInstance ,
1590
- type : string ,
1591
- props : Props ,
1592
- ) {
1593
- if ( __DEV__ ) {
1594
- // $FlowFixMe[incompatible-type]: Only Element or Document can be parent nodes.
1595
- const parentNode : Element | Document | null = parentInstance . parentNode ;
1596
- if ( parentNode !== null )
1597
- warnForInsertedHydratedElement ( parentNode , type , props ) ;
1598
- }
1599
- }
1600
-
1601
- export function didNotFindHydratableTextInstanceWithinSuspenseInstance (
1602
- parentInstance : SuspenseInstance ,
1603
- text : string ,
1604
- ) {
1605
- if ( __DEV__ ) {
1606
- // $FlowFixMe[incompatible-type]: Only Element or Document can be parent nodes.
1607
- const parentNode : Element | Document | null = parentInstance . parentNode ;
1608
- if ( parentNode !== null ) warnForInsertedHydratedText ( parentNode , text ) ;
1609
- }
1610
- }
1611
-
1612
- export function didNotFindHydratableSuspenseInstanceWithinSuspenseInstance (
1613
- parentInstance : SuspenseInstance ,
1614
- ) {
1615
- if ( __DEV__ ) {
1616
- // const parentNode: Element | Document | null = parentInstance.parentNode;
1617
- // TODO: warnForInsertedHydratedSuspense(parentNode);
1618
- }
1619
- }
1620
-
1621
- export function didNotFindHydratableInstance (
1622
- parentType : string ,
1623
- parentProps : Props ,
1624
- parentInstance : Instance ,
1625
- type : string ,
1626
- props : Props ,
1627
- ) {
1628
- if ( __DEV__ ) {
1629
- warnForInsertedHydratedElement ( parentInstance , type , props ) ;
1630
- }
1631
- }
1632
-
1633
- export function didNotFindHydratableTextInstance (
1634
- parentType : string ,
1635
- parentProps : Props ,
1636
- parentInstance : Instance ,
1637
- text : string ,
1638
- ) {
1639
- if ( __DEV__ ) {
1640
- warnForInsertedHydratedText ( parentInstance , text ) ;
1641
- }
1642
- }
1643
-
1644
- export function didNotFindHydratableSuspenseInstance (
1645
- parentType : string ,
1646
- parentProps : Props ,
1647
- parentInstance : Instance ,
1648
- ) {
1649
- if ( __DEV__ ) {
1650
- // TODO: warnForInsertedHydratedSuspense(parentInstance);
1651
- }
1652
- }
1653
-
1654
- export function errorHydratingContainer ( parentContainer : Container ) : void {
1655
- if ( __DEV__ ) {
1656
- // TODO: This gets logged by onRecoverableError, too, so we should be
1657
- // able to remove it.
1658
- console . error (
1659
- 'An error occurred during hydration. The server HTML was replaced with client content in <%s>.' ,
1660
- parentContainer . nodeName . toLowerCase ( ) ,
1661
- ) ;
1662
- }
1663
- }
1664
-
1665
1530
// -------------------
1666
1531
// Test Selectors
1667
1532
// -------------------
0 commit comments