PoC Migrating from React.ComponentType to React.ReactElement - #4431
Draft
Loloekk wants to merge 6 commits into
Draft
PoC Migrating from React.ComponentType to React.ReactElement#4431Loloekk wants to merge 6 commits into
Loloekk wants to merge 6 commits into
Conversation
Loloekk
force-pushed
the
@Loloekk/PoC-migrate-change-original-source
branch
from
July 30, 2026 13:46
749de62 to
2492c9a
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the example app’s custom StackContainer/TabsContainer route-config model to pass prebuilt React elements (instead of component types), and adds several PoC test screens + a documented “simple stack navigation” scenario under apps/src/tests/PoC.
Changes:
- Switched stack/tabs route configs from
Component: React.ComponentTypetoelement: React.ReactElementand updated container rendering/mapping accordingly. - Added PoC screens (
TestStackPoC,TestTabsPoC) and a new documented scenario (test-stack-simple-navPoC). - Updated the example app test surface (issue-test exports) and TypeScript config for
apps/.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/tsconfig.json | Excludes src/tests/** from the apps TS project. |
| apps/src/tests/PoC/TestTabsPoC.tsx | New PoC screen for tabs container behavior with shared vs inline elements. |
| apps/src/tests/PoC/TestStackPoC.tsx | New PoC screen for stack container behavior with shared vs inline elements. |
| apps/src/tests/PoC/test-stack-simple-navPoC/scenario.md | New written scenario for validating stack push/pop and gestures. |
| apps/src/tests/PoC/test-stack-simple-navPoC/scenario-description.ts | Scenario metadata for the new “simple stack navigation” scenario. |
| apps/src/tests/PoC/test-stack-simple-navPoC/index.tsx | Scenario implementation using StackContainer + shared test components. |
| apps/src/tests/PoC/index.ts | Barrel exports for PoC scenarios. |
| apps/src/tests/issue-tests/TestPoC.tsx | New issue-test PoC screen demonstrating context/provider behavior per “slot”. |
| apps/src/tests/issue-tests/index.ts | Comments out most issue-test exports; leaves only TestPoC exported. |
| apps/src/shared/containers/tabs/TabsContainerItem.types.ts | Updates item prop from Component to element. |
| apps/src/shared/containers/tabs/TabsContainerItem.tsx | Renders element and wraps in SafeAreaView when needed. |
| apps/src/shared/containers/tabs/TabsContainer.types.tsx | Changes tab route config shape to use element. |
| apps/src/shared/containers/tabs/TabsContainer.tsx | Resolves route content via useElementsByName and passes element to items. |
| apps/src/shared/containers/tabs/reducer.tsx | Adjusts config-to-route conversion to omit element. |
| apps/src/shared/containers/stack/StackContainer.types.ts | Changes stack route config shape to use element. |
| apps/src/shared/containers/stack/StackContainer.tsx | Resolves route content via useElementsByName and renders element. |
| apps/src/shared/containers/stack/reducer.tsx | Adjusts config-to-route conversion to omit element. |
| apps/src/shared/containers/shared/use-elements-by-name.ts | Renames/migrates mapping hook to return elements by route name. |
Suppressed comments (2)
apps/src/shared/containers/shared/use-elements-by-name.ts:13
- useElementsByName currently only reads
config.element. There are still many route configs in the app tests that use the legacyComponentfield (e.g.apps/src/tests/single-feature-tests/tabs/test-tabs-simple-nav/index.tsx:51-65andapps/src/tests/component-integration-tests/scroll-view-marker/test-stack-svm-lift-on-scroll/index.tsx:19-35). With the new container implementation, those scenarios will hit the "No config matches" error at runtime because the map value becomesundefined. Consider supporting legacyComponentby creating an element whenelementisn’t provided (or migrate all callers in this PR).
apps/src/shared/containers/tabs/TabsContainerItem.tsx:60 safeAreaConfigurationWithDefaultis computed (and used to decide whether to wrap inSafeAreaView), but it isn’t actually passed toSafeAreaView. This means the intended default edges (e.g.{ bottom: true }on Android) are ignored.
const safeAreaConfigurationWithDefault = getSafeAreaViewEdges(
safeAreaConfiguration?.edges,
);
const anySAVEdgeSet = Object.values(safeAreaConfigurationWithDefault).some(
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+100
to
+102
| {/* Clone so multiple stack entries of the same route get distinct instances. | ||
| {React.cloneElement(element)} */} | ||
| {element} |
Comment on lines
+1
to
+4
| // // @ts-nocheck | ||
|
|
||
| export { default as Test42 } from './Test42'; // [E2E skipped]: can't check orientation, unclear problem description | ||
| export { default as Test111 } from './Test111'; // [E2E skipped]: can't check flickering | ||
| export { default as Test263 } from './Test263'; // [E2E skipped]: example differs from PR, even if changed the problem still occurs | ||
| export { default as Test349 } from './Test349'; // [E2E skipped]: can't check autofill easily, wrong prop name | ||
| export { default as Test364 } from './Test364'; // [E2E skipped]: tabBarVisible prop doesn't exist anymore, suggested solution is to change navigator hierarchy (proposed in PR and in react-navigation docs) | ||
| export { default as Test432 } from './Test432'; // [E2E created] | ||
| export { default as Test528 } from './Test528'; // [E2E created](iOS): Detox supports changing orientation only on iOS | ||
| export { default as Test550 } from './Test550'; // [E2E skipped]: the prop does not work, when fixed we can add the test | ||
| export { default as Test556 } from './Test556'; // [E2E skipped]: can't check flickering nor non-deterministic white screen bug | ||
| export { default as Test564 } from './Test564'; // [E2E skipped]: issue still present | ||
| export { default as Test577 } from './Test577'; // [E2E created](iOS): issue is related to iOS modal | ||
| export { default as Test593 } from './Test593'; // [E2E created] | ||
| export { default as Test619 } from './Test619'; // [E2E skipped]: can't check components jumping | ||
| export { default as Test624 } from './Test624'; // [E2E skipped]: PR changed library internals, test screen seems unrelated | ||
| export { default as Test640 } from './Test640'; // [E2E created] | ||
| export { default as Test642 } from './Test642'; // [E2E skipped]: can't check status bar visibility/style | ||
| export { default as Test645 } from './Test645'; // [E2E created](iOS): headerLargeTitle is supported only on iOS | ||
| export { default as Test648 } from './Test648'; // [E2E skipped]: can't check animation in a meaningful way | ||
| export { default as Test649 } from './Test649'; // [E2E created](iOS): headerLargeTitle is supported only on iOS | ||
| export { default as Test654 } from './Test654'; // [E2E created](iOS): issue related to iOS native back button | ||
| export { default as Test658 } from './Test658'; // [E2E created] | ||
| export { default as Test662 } from './Test662'; // [E2E skipped]: can't check animation in a meaningful way | ||
| export { default as Test691 } from './Test691'; // [E2E created](iOS): issue related to iOS modal behavior | ||
| export { default as Test702 } from './Test702'; // [E2E skipped]: can't check animation in a meaningful way | ||
| export { default as Test706 } from './Test706'; // [E2E skipped]: can't check font weight | ||
| export { default as Test726 } from './Test726'; // [E2E created](iOS): issue related to iOS | ||
| export { default as Test748 } from './Test748'; // [E2E skipped]: issue unclear, Test432 covers more complex cases already | ||
| export { default as Test750 } from './Test750'; // [E2E skipped]: can't check insets | ||
| export { default as Test758 } from './Test758'; // [E2E created](iOS): PR related to iOS search bar | ||
| export { default as Test761 } from './Test761'; // [E2E skipped]: can't check animation in a meaningful way | ||
| export { default as Test779 } from './Test779'; // [E2E skipped]: can't check animation in a meaningful way | ||
| export { default as Test780 } from './Test780'; // [E2E skipped]: can't use native swipe back gesture | ||
| export { default as Test791 } from './Test791'; // [E2E created](iOS): issue related to iOS | ||
| export { default as Test800 } from './Test800'; | ||
| export { default as Test817 } from './Test817'; | ||
| export { default as Test830 } from './Test830'; | ||
| export { default as Test831 } from './Test831'; | ||
| export { default as Test844 } from './Test844'; | ||
| export { default as Test852 } from './Test852'; | ||
| export { default as Test860 } from './Test860'; | ||
| export { default as Test861 } from './Test861'; | ||
| export { default as Test865 } from './Test865'; | ||
| export { default as Test881 } from './Test881'; | ||
| export { default as Test887 } from './Test887'; | ||
| export { default as Test913 } from './Test913'; | ||
| export { default as Test999 } from './Test999'; | ||
| export { default as Test1017 } from './Test1017'; | ||
| export { default as Test1031 } from './Test1031'; | ||
| export { default as Test1032 } from './Test1032'; | ||
| export { default as Test1036 } from './Test1036'; | ||
| export { default as Test1072 } from './Test1072'; | ||
| export { default as Test1084 } from './Test1084'; | ||
| export { default as Test1091 } from './Test1091'; | ||
| export { default as Test1096 } from './Test1096'; | ||
| export { default as Test1097 } from './Test1097'; | ||
| export { default as Test1153 } from './Test1153'; | ||
| export { default as Test1157 } from './Test1157'; | ||
| export { default as Test1162 } from './Test1162'; | ||
| export { default as Test1166 } from './Test1166'; | ||
| export { default as Test1188 } from './Test1188'; | ||
| export { default as Test1190 } from './Test1190'; | ||
| export { default as TestFreeze } from './TestFreeze'; | ||
| export { default as Test1198 } from './Test1198'; | ||
| export { default as Test1204 } from './Test1204'; | ||
| export { default as Test1209 } from './Test1209'; | ||
| export { default as Test1213 } from './Test1213'; | ||
| export { default as Test1214 } from './Test1214'; | ||
| export { default as Test1227 } from './Test1227'; | ||
| export { default as Test1228 } from './Test1228'; | ||
| export { default as Test1259 } from './Test1259'; | ||
| export { default as Test1260 } from './Test1260'; | ||
| export { default as Test1296 } from './Test1296'; | ||
| export { default as Test1299 } from './Test1299'; | ||
| export { default as Test1391 } from './Test1391'; | ||
| export { default as Test1419 } from './Test1419'; | ||
| export { default as Test1463 } from './Test1463'; | ||
| export { default as Test1473 } from './Test1473'; | ||
| export { default as Test1476 } from './Test1476'; | ||
| export { default as Test1509 } from './Test1509'; | ||
| export { default as Test1539 } from './Test1539'; | ||
| export { default as Test1645 } from './Test1645'; | ||
| export { default as Test1646 } from './Test1646'; | ||
| // export { default as Test1649 } from './Test1649'; | ||
| export { default as Test1671 } from './Test1671'; | ||
| export { default as Test1683 } from './Test1683'; | ||
| export { default as Test1726 } from './Test1726'; | ||
| export { default as Test1791 } from './Test1791'; | ||
| export { default as Test1802 } from './Test1802'; | ||
| export { default as Test1829 } from './Test1829'; | ||
| export { default as Test1844 } from './Test1844'; | ||
| export { default as Test1864 } from './Test1864'; | ||
| export { default as Test1970 } from './Test1970'; | ||
| export { default as Test1975 } from './Test1975'; | ||
| export { default as Test1981 } from './Test1981'; | ||
| export { default as Test2002 } from './Test2002'; | ||
| export { default as Test2008 } from './Test2008'; | ||
| export { default as Test2028 } from './Test2028'; | ||
| export { default as Test2048 } from './Test2048'; | ||
| export { default as Test2069 } from './Test2069'; | ||
| export { default as Test2118 } from './Test2118'; | ||
| export { default as Test2125 } from './Test2125'; // [E2E skipped]: issue happens nondeterministically | ||
| export { default as Test2167 } from './Test2167'; | ||
| export { default as Test2175 } from './Test2175'; | ||
| export { default as Test2184 } from './Test2184'; | ||
| export { default as Test2223 } from './Test2223'; | ||
| export { default as Test2227 } from './Test2227'; | ||
| export { default as Test2229 } from './Test2229'; | ||
| export { default as Test2232 } from './Test2232'; | ||
| export { default as Test2235 } from './Test2235'; | ||
| export { default as Test2252 } from './Test2252'; | ||
| export { default as Test2271 } from './Test2271'; | ||
| export { default as Test2282 } from './Test2282'; | ||
| export { default as Test2317 } from './Test2317'; | ||
| export { default as Test2320 } from './Test2320'; | ||
| export { default as Test2332 } from './Test2332'; | ||
| export { default as Test2379 } from './Test2379'; | ||
| export { default as Test2395 } from './Test2395'; | ||
| export { default as Test2466 } from './Test2466'; | ||
| export { default as Test2522 } from './Test2522'; | ||
| export { default as Test2538 } from './Test2538'; | ||
| export { default as Test2543 } from './Test2543'; // [E2E created](iOS): issue related to iOS formSheet initial detent | ||
| export { default as Test2552 } from './Test2552'; | ||
| export { default as Test2559 } from './Test2559'; | ||
| export { default as Test2560 } from './Test2560'; | ||
| export { default as Test2611 } from './Test2611'; | ||
| export { default as Test2631 } from './Test2631'; | ||
| export { default as Test2668 } from './Test2668'; | ||
| export { default as Test2675 } from './Test2675'; | ||
| export { default as Test2714 } from './Test2714'; | ||
| export { default as Test2717 } from './Test2717'; | ||
| export { default as Test2767 } from './Test2767'; | ||
| export { default as Test2789 } from './Test2789'; | ||
| export { default as Test2809 } from './Test2809'; | ||
| export { default as Test2811 } from './Test2811'; | ||
| export { default as Test2819 } from './Test2819'; | ||
| export { default as Test2842 } from './Test2842'; // [E2E created](iOS): issue is related to iOS | ||
| export { default as Test2855 } from './Test2855'; | ||
| export { default as Test2877 } from './Test2877'; // [E2E created](iOS): issue is related to formSheet on iOS | ||
| export { default as Test2895 } from './Test2895'; | ||
| export { default as Test2899 } from './Test2899'; | ||
| export { default as Test2933 } from './Test2933'; | ||
| export { default as Test2926 } from './Test2926'; // [E2E created](iOS): PR related to iOS search bar | ||
| export { default as Test2963 } from './Test2963'; // [E2E created](iOS): issue related to iOS | ||
| export { default as Test3004 } from './Test3004'; | ||
| export { default as Test3006 } from './Test3006'; | ||
| export { default as Test3045 } from './Test3045'; | ||
| export { default as Test3074 } from './Test3074'; | ||
| export { default as Test3093 } from './Test3093'; | ||
| export { default as Test3111 } from './Test3111'; | ||
| export { default as Test3168 } from './Test3168'; | ||
| export { default as Test3173 } from './Test3173'; | ||
| export { default as Test3212 } from './Test3212'; | ||
| export { default as Test3236 } from './Test3236'; | ||
| export { default as Test3239 } from './Test3239'; | ||
| export { default as Test3248 } from './Test3248'; | ||
| export { default as Test3265 } from './Test3265'; | ||
| export { default as Test3271 } from './Test3271'; | ||
| export { default as Test3282 } from './Test3282'; | ||
| export { default as Test3288 } from './Test3288'; | ||
| export { default as Test3336 } from './Test3336'; | ||
| export { default as Test3342 } from './Test3342'; | ||
| export { default as Test3345 } from './Test3345'; | ||
| export { default as Test3346 } from './Test3346'; | ||
| export { default as Test3369 } from './Test3369'; | ||
| export { default as Test3379 } from './Test3379'; | ||
| export { default as Test3422 } from './Test3422'; | ||
| export { default as Test3425 } from './Test3425'; | ||
| export { default as Test3443 } from './Test3443'; | ||
| export { default as Test3446 } from './Test3446'; | ||
| export { default as Test3450 } from './Test3450'; | ||
| export { default as Test3480 } from './Test3480'; | ||
| export { default as Test3492 } from './Test3492'; | ||
| export { default as Test3521 } from './Test3521'; | ||
| export { default as Test3522 } from './Test3522'; | ||
| export { default as Test3564 } from './Test3564'; | ||
| export { default as Test3566 } from './Test3566'; | ||
| export { default as Test3568 } from './Test3568'; | ||
| export { default as Test3576 } from './Test3576'; | ||
| export { default as Test3596 } from './Test3596'; | ||
| export { default as Test3606 } from './Test3606'; | ||
| export { default as Test3611 } from './Test3611'; | ||
| export { default as Test3617 } from './Test3617'; | ||
| export { default as Test3636 } from './Test3636'; | ||
| export { default as Test3760 } from './Test3760'; | ||
| export { default as Test3770 } from './Test3770'; | ||
| export { default as Test3793 } from './Test3793'; | ||
| export { default as Test3816 } from './Test3816'; | ||
| export { default as Test3833 } from './Test3833'; | ||
| export { default as Test3835 } from './Test3835'; | ||
| export { default as Test3867 } from './Test3867'; | ||
| export { default as Test3885 } from './Test3885'; | ||
| export { default as Test3910 } from './Test3910'; | ||
| export { default as Test4027 } from './Test4027'; | ||
| export { default as Test4064 } from './Test4064'; | ||
| export { default as Test4090 } from './Test4090'; | ||
| export { default as Test4155 } from './Test4155'; | ||
| export { default as Test4161 } from './Test4161'; | ||
| export { default as Test4220 } from './Test4220'; | ||
| export { default as Test4240 } from './Test4240'; | ||
| export { default as Test4244 } from './Test4244'; | ||
| export { default as Test4258 } from './Test4258'; | ||
| export { default as Test4264 } from './Test4264'; | ||
| export { default as Test4265 } from './Test4265'; | ||
| export { default as Test4276 } from './Test4276'; | ||
| export { default as Test4351 } from './Test4351'; | ||
| export { default as Test4357 } from './Test4357'; | ||
| export { default as Test4361 } from './Test4361'; | ||
| export { default as TestScreenAnimation } from './TestScreenAnimation'; | ||
| // The following test was meant to demo the "go back" gesture using Reanimated | ||
| // but the associated PR in react-navigation is currently put on hold | ||
| // export { default as TestScreenAnimationV5 } from './TestScreenAnimationV5'; | ||
| export { default as TestHeader } from './TestHeader'; | ||
| export { default as TestPreload } from './TestPreload'; | ||
| export { default as TestActivityStateProgression } from './TestActivityStateProgression'; | ||
| export { default as TestHeaderTitle } from './TestHeaderTitle'; | ||
| export { default as TestHeaderHeight } from './TestHeaderHeight'; | ||
| export { default as TestModalNavigation } from './TestModalNavigation'; | ||
| export { default as TestMemoryLeak } from './TestMemoryLeak'; | ||
| export { default as TestFormSheet } from './TestFormSheet'; | ||
| export { default as TestAndroidTransitions } from './TestAndroidTransitions'; | ||
| export { default as TestAnimation } from './TestAnimation'; | ||
| export { default as TestBottomTabs } from './TestBottomTabs'; | ||
| export { default as TestBottomTabsOrientation } from './TestBottomTabsOrientation'; | ||
| export { default as TestScreenStack } from './TestScreenStack'; | ||
| export { default as TestSplit } from './TestSplit'; | ||
| export { default as TestSafeAreaViewIOS } from './TestSafeAreaViewIOS'; | ||
| export { default as TestStackNesting } from './TestStackNesting'; | ||
| export { default as TestScreenFooterKeyboardInsets } from './TestScreenFooterKeyboardInsets'; | ||
| // export { default as Test42 } from './Test42'; // [E2E skipped]: can't check orientation, unclear problem description | ||
| // export { default as Test111 } from './Test111'; // [E2E skipped]: can't check flickering |
Loloekk
force-pushed
the
@Loloekk/PoC-migrate-change-original-source
branch
from
August 4, 2026 06:53
cc71840 to
470ceb9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Changes
Before & after - visual documentation
Test plan
Checklist