signals
signals copied to clipboard
Error when using signals with react-native navigation
The error is easy to replicate. packadge.json
{
"name": "",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
},
"dependencies": {
"@preact/signals-react": "^1.2.1",
"@react-navigation/bottom-tabs": "^6.4.0",
"@react-navigation/native": "^6.0.13",
"@react-navigation/native-stack": "^6.9.1",
"i18next": "^22.0.4",
"react": "18.1.0",
"react-i18next": "^12.0.0",
"react-native": "0.70.3",
"react-native-gesture-handler": "^2.8.0",
"react-native-material-dropdown": "^0.11.1",
"react-native-paper": "^5.0.0-rc.8",
"react-native-safe-area-context": "^4.4.1",
"react-native-screens": "^3.16.0",
"react-native-svg": "^13.4.0",
"react-native-vector-icons": "^9.2.0"
},
"devDependencies": {
"@babel/core": "^7.12.9",
"@babel/runtime": "^7.12.5",
"@react-native-community/eslint-config": "^2.0.0",
"@tsconfig/react-native": "^2.0.2",
"@types/jest": "^26.0.23",
"@types/react": "^18.0.21",
"@types/react-native": "^0.70.4",
"@types/react-native-material-dropdown": "^0.11.5",
"@types/react-test-renderer": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.37.0",
"@typescript-eslint/parser": "^5.37.0",
"babel-jest": "^26.6.3",
"eslint": "^7.32.0",
"jest": "^26.6.3",
"metro-react-native-babel-preset": "0.72.3",
"react-test-renderer": "18.1.0",
"typescript": "^4.8.3"
},
"jest": {
"preset": "react-native",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
}
}
How to reproduce.
- Setup react-native navigation example
const App = () => (
<NavigationContainer>
<Stack.Navigator
initialRouteName={initialRouteName}
screenOptions={noHeaderOption}>
<Stack.Screen name="Login" component={Login} />
</Stack.Navigator>
</NavigationContainer>
);
- use react signals here I have another file containing an exported signal
import {Signal, signal} from '@preact/signals-react';
import {User} from '../types';
const user: Signal<User> = signal(null);
// get from session storage?
export const initialRouteName = user ? 'BottomTab' : 'Login';
export default user;
Once I import this signal inside the Login component and use it there, I get the error Error: A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found 'Screen' for the screen 'Login'). To render this component in the navigator, pass it in the 'component' prop to 'Screen'.
This error is located at:
in NativeStackNavigator (created by App)
in EnsureSingleNavigator
in BaseNavigationContainer
in ThemeProvider
in NavigationContainerInner (created by App)
in App (created by Main)
in ThemeProvider (created by Provider)
in RCTView (created by View)
in View (created by Portal.Host)
in Portal.Host (created by Provider)
in Provider (created by Main)
in Main
in RCTView (created by View)
in View (created by AppContainer)
in RCTView (created by View)
in View (created by AppContainer)
in AppContainer
in thedoc(RootComponent), js engine: hermes
I am running into this same error.
same here..
This issues happens in react-navigation
as well
I've disabled these lines and it works as expected. at this file File
// React.createElement = WrapJsx(React.createElement);
// JsxDev.jsx && /* */ (JsxDev.jsx = WrapJsx(JsxDev.jsx));
// JsxPro.jsx && /* */ (JsxPro.jsx = WrapJsx(JsxPro.jsx));
// JsxDev.jsxs && /* */ (JsxDev.jsxs = WrapJsx(JsxDev.jsxs));
// JsxPro.jsxs && /* */ (JsxPro.jsxs = WrapJsx(JsxPro.jsxs));
// JsxDev.jsxDEV && /**/ (JsxDev.jsxDEV = WrapJsx(JsxDev.jsxDEV));
// JsxPro.jsxDEV && /**/ (JsxPro.jsxDEV = WrapJsx(JsxPro.jsxDEV));
So, I suggest to disable these lines at ios
and android
platforms. @JoviDeCroock
Facing the same issue with a BottomTabNavigator in React Native. Disabling the lines as mentioned above didnt work for me either.
Facing the same problem.
I fixed this issue (it works for 1.2.1 version). You need to apply this patch for @react-navigation/core:
diff --git a/node_modules/@react-navigation/core/src/Group.tsx b/node_modules/@react-navigation/core/src/Group.tsx
index 352ba31..893d2c2 100644
--- a/node_modules/@react-navigation/core/src/Group.tsx
+++ b/node_modules/@react-navigation/core/src/Group.tsx
@@ -12,3 +12,4 @@ export default function Group<
/* istanbul ignore next */
return null;
}
+Group.__isGroup = true;
\ No newline at end of file
diff --git a/node_modules/@react-navigation/core/src/Screen.tsx b/node_modules/@react-navigation/core/src/Screen.tsx
index 4ca4306..f116e61 100644
--- a/node_modules/@react-navigation/core/src/Screen.tsx
+++ b/node_modules/@react-navigation/core/src/Screen.tsx
@@ -15,3 +15,4 @@ export default function Screen<
/* istanbul ignore next */
return null;
}
+Screen.__isScreen = true;
\ No newline at end of file
diff --git a/node_modules/@react-navigation/core/src/useNavigationBuilder.tsx b/node_modules/@react-navigation/core/src/useNavigationBuilder.tsx
index 76442df..e1c8632 100644
--- a/node_modules/@react-navigation/core/src/useNavigationBuilder.tsx
+++ b/node_modules/@react-navigation/core/src/useNavigationBuilder.tsx
@@ -93,7 +93,7 @@ const getRouteConfigsFromChildren = <
ScreenConfigWithParent<State, ScreenOptions, EventMap>[]
>((acc, child) => {
if (React.isValidElement(child)) {
- if (child.type === Screen) {
+ if (child.type?.__isScreen) {
// We can only extract the config from `Screen` elements
// If something else was rendered, it's probably a bug
@@ -121,7 +121,7 @@ const getRouteConfigsFromChildren = <
return acc;
}
- if (child.type === React.Fragment || child.type === Group) {
+ if (child.type === React.Fragment || child.type?.__isGroup) {
if (!isValidKey(child.props.navigationKey)) {
throw new Error(
`Got an invalid 'navigationKey' prop (${JSON.stringify(