@@ -785,6 +785,230 @@ describe('ProfilingCache', () => {
785785 ` ) ;
786786 } ) ;
787787
788+ // @reactVersion >= 16.9
789+ it ( 'should use only direct custom hook values when formatting hook paths' , ( ) => {
790+ function useConditionalStateHook ( isRandom ) {
791+ const x = isRandom ? 1 : 0 ;
792+ const [ value , setValue ] = React . useState ( x ) ;
793+ return [ value , setValue ] ;
794+ }
795+
796+ function useCustomHook ( label ) {
797+ React . useDebugValue ( label ) ;
798+ const [ value , setValue ] = React . useState ( label ) ;
799+ return [ value , setValue ] ;
800+ }
801+
802+ let setTopLevelState = null ;
803+ let setConditionalState = null ;
804+ let setNumberLabelState = null ;
805+ let setStringLabelState = null ;
806+ let setUndefinedLabelState = null ;
807+ let setMissingLabelState = null ;
808+
809+ const Component = ( ) => {
810+ const [ , _setTopLevelState ] = React . useState ( 4 ) ;
811+ setTopLevelState = _setTopLevelState ;
812+
813+ const [ , _setConditionalState ] = useConditionalStateHook ( true ) ;
814+ setConditionalState = _setConditionalState ;
815+
816+ const [ , _setNumberLabelState ] = useCustomHook ( 10 ) ;
817+ setNumberLabelState = _setNumberLabelState ;
818+
819+ const [ , _setStringLabelState ] = useCustomHook ( '10' ) ;
820+ setStringLabelState = _setStringLabelState ;
821+
822+ const [ , _setUndefinedLabelState ] = useCustomHook ( undefined ) ;
823+ setUndefinedLabelState = _setUndefinedLabelState ;
824+
825+ const [ , _setMissingLabelState ] = useCustomHook ( ) ;
826+ setMissingLabelState = _setMissingLabelState ;
827+
828+ return null ;
829+ } ;
830+
831+ utils . act ( ( ) => render ( < Component /> ) ) ;
832+
833+ const realSetTopLevelState = setTopLevelState ;
834+ const realSetConditionalState = setConditionalState ;
835+ const realSetNumberLabelState = setNumberLabelState ;
836+ const realSetStringLabelState = setStringLabelState ;
837+ const realSetUndefinedLabelState = setUndefinedLabelState ;
838+ const realSetMissingLabelState = setMissingLabelState ;
839+
840+ utils . act ( ( ) => startRecording ( ) ) ;
841+
842+ utils . act ( ( ) => realSetTopLevelState ( 5 ) ) ;
843+ utils . act ( ( ) => realSetConditionalState ( 2 ) ) ;
844+ utils . act ( ( ) => realSetNumberLabelState ( 11 ) ) ;
845+ utils . act ( ( ) => realSetStringLabelState ( '11' ) ) ;
846+ utils . act ( ( ) => realSetUndefinedLabelState ( 'defined' ) ) ;
847+ utils . act ( ( ) => realSetMissingLabelState ( 'later' ) ) ;
848+
849+ let recorded ;
850+ utils . act ( ( ) => {
851+ recorded = endRecording ( ) ;
852+ } ) ;
853+
854+ const changeDescriptions = recorded . map ( commit => {
855+ const descriptions = toChangeDescriptionsByDisplayName (
856+ commit . filter ( c => c . displayName === 'Component' ) ,
857+ ) ;
858+ return new Map (
859+ Array . from ( descriptions . entries ( ) ) . map ( ( [ displayName , entry ] ) => [
860+ displayName ,
861+ {
862+ ...entry ,
863+ hooks :
864+ entry . hooks == null
865+ ? entry . hooks
866+ : entry . hooks . map ( ( { hookSource, ...hook } ) => hook ) ,
867+ } ,
868+ ] ) ,
869+ ) ;
870+ } ) ;
871+
872+ expect ( changeDescriptions ) . toHaveLength ( 6 ) ;
873+
874+ // 1st render: top-level useState(4)
875+ expect ( changeDescriptions [ 0 ] ) . toMatchInlineSnapshot ( `
876+ Map {
877+ "Component" => {
878+ "context": false,
879+ "didHooksChange": true,
880+ "hooks": [
881+ {
882+ "hookIndex": 0,
883+ "hookName": "State",
884+ "hookPath": [
885+ "State",
886+ ],
887+ },
888+ ],
889+ "isFirstMount": false,
890+ "props": [],
891+ "state": null,
892+ },
893+ }
894+ ` ) ;
895+
896+ // 2nd render: useConditionalStateHook with subhook state derived from x
897+ expect ( changeDescriptions [ 1 ] ) . toMatchInlineSnapshot ( `
898+ Map {
899+ "Component" => {
900+ "context": false,
901+ "didHooksChange": true,
902+ "hooks": [
903+ {
904+ "hookIndex": 1,
905+ "hookName": "State",
906+ "hookPath": [
907+ "ConditionalStateHook",
908+ "State",
909+ ],
910+ },
911+ ],
912+ "isFirstMount": false,
913+ "props": [],
914+ "state": null,
915+ },
916+ }
917+ ` ) ;
918+
919+ // 3rd render: useCustomHook(10)
920+ expect ( changeDescriptions [ 2 ] ) . toMatchInlineSnapshot ( `
921+ Map {
922+ "Component" => {
923+ "context": false,
924+ "didHooksChange": true,
925+ "hooks": [
926+ {
927+ "hookIndex": 2,
928+ "hookName": "State",
929+ "hookPath": [
930+ "CustomHook(10)",
931+ "State",
932+ ],
933+ },
934+ ],
935+ "isFirstMount": false,
936+ "props": [],
937+ "state": null,
938+ },
939+ }
940+ ` ) ;
941+
942+ // 4th render: useCustomHook("10")
943+ expect ( changeDescriptions [ 3 ] ) . toMatchInlineSnapshot ( `
944+ Map {
945+ "Component" => {
946+ "context": false,
947+ "didHooksChange": true,
948+ "hooks": [
949+ {
950+ "hookIndex": 3,
951+ "hookName": "State",
952+ "hookPath": [
953+ "CustomHook("10")",
954+ "State",
955+ ],
956+ },
957+ ],
958+ "isFirstMount": false,
959+ "props": [],
960+ "state": null,
961+ },
962+ }
963+ ` ) ;
964+
965+ // 5th render: useCustomHook(undefined)
966+ expect ( changeDescriptions [ 4 ] ) . toMatchInlineSnapshot ( `
967+ Map {
968+ "Component" => {
969+ "context": false,
970+ "didHooksChange": true,
971+ "hooks": [
972+ {
973+ "hookIndex": 4,
974+ "hookName": "State",
975+ "hookPath": [
976+ "CustomHook",
977+ "State",
978+ ],
979+ },
980+ ],
981+ "isFirstMount": false,
982+ "props": [],
983+ "state": null,
984+ },
985+ }
986+ ` ) ;
987+
988+ // 6th render: useCustomHook() without an argument
989+ expect ( changeDescriptions [ 5 ] ) . toMatchInlineSnapshot ( `
990+ Map {
991+ "Component" => {
992+ "context": false,
993+ "didHooksChange": true,
994+ "hooks": [
995+ {
996+ "hookIndex": 5,
997+ "hookName": "State",
998+ "hookPath": [
999+ "CustomHook",
1000+ "State",
1001+ ],
1002+ },
1003+ ],
1004+ "isFirstMount": false,
1005+ "props": [],
1006+ "state": null,
1007+ },
1008+ }
1009+ ` ) ;
1010+ } ) ;
1011+
7881012 // @reactVersion >= 16.9
7891013 it ( 'should collect data for each rendered fiber' , ( ) => {
7901014 const Parent = ( { count} ) => {
0 commit comments