Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ BUG ] Error: Element type is invalid: expected a string #142

Open
MikeSchlosser16 opened this issue May 7, 2024 · 3 comments
Open

[ BUG ] Error: Element type is invalid: expected a string #142

MikeSchlosser16 opened this issue May 7, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@MikeSchlosser16
Copy link

MikeSchlosser16 commented May 7, 2024

Describe the bug
When using Dialog, even in the base project, I get the following error (I do have the PortalHost component). It appears to be an issue with DialogContent in particular. It's very possible I'm doing something wrong :)

 ERROR  Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check the render method of `ContentNativeDialog`.

This error is located at:
    in RCTView (created by CssInterop.View)
    in CssInterop.View (created by Pressable)
    in Pressable (created by Pressable)
    in CssInterop.Pressable (created by CloseNativeDialog)
    in CloseNativeDialog (created by ContentNativeDialog)
    in RCTView (created by View)
    in View (created by CssInterop.View)
    in CssInterop.View (created by ContentNativeDialog)
    in ContentNativeDialog (created by ContentNativeDialog)
    in RCTView (created by CssInterop.View)
    in CssInterop.View (created by AnimatedComponent(View))
    in AnimatedComponent(View)
    in Unknown (created by DialogOverlayNative)
    in RCTView (created by CssInterop.View)
    in CssInterop.View (created by Pressable)
    in Pressable (created by Pressable)
    in CssInterop.Pressable (created by OverlayNativeDialog)
    in OverlayNativeDialog (created by DialogOverlayNative)
    in _c3 (created by ContentNativeDialog)
    in PortalHost (created by RootLayout)
    in ThemeProvider (created by RootLayout)
    in RootLayout
    in Try
    in Unknown
    in Unknown (created by Route())
    in Suspense (created by Route())
    in Route (created by Route())
    in Route() (created by ContextNavigator)
    in RNCSafeAreaProvider (created by SafeAreaProvider)
    in SafeAreaProvider (created by wrapper)
    in wrapper (created by ContextNavigator)
    in EnsureSingleNavigator
    in BaseNavigationContainer
    in ThemeProvider
    in NavigationContainerInner (created by ContextNavigator)
    in ContextNavigator (created by ExpoRoot)
    in ExpoRoot (created by App)
    in App (created by withDevTools(App))
    in withDevTools(App)
    in RCTView (created by CssInterop.View)
    in CssInterop.View (created by AppContainer)
    in RCTView (created by CssInterop.View)
    in CssInterop.View (created by AppContainer)
    in AppContainer
    in main(RootComponent), js engine: hermes

It's worth noting that AlertDialog does work as expected. I've tried also just using the template start project, and the issue remains.

To Reproduce
Steps to reproduce the behavior:

  1. git clone https://github.com/mrzachnugent/react-native-reusables.git
  2. cp -R react-native-reusables/apps/starter-base/ ./my-project
  3. cd my-project && npm i
  4. npm run ios
  5. npx @react-native-reusables/cli@latest add alert-dialog
  6. Replace index.tsx body with the following:
import * as React from "react";
import { Button } from "~/components/ui/button";
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "~/components/ui/dialog";
import { Text } from "~/components/ui/text";

export default function Screen() {
  const [progress, setProgress] = React.useState(78);

  function updateProgressValue() {
    setProgress(Math.floor(Math.random() * 100));
  }
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button variant="outline">
          <Text>Edit Profile</Text>
        </Button>
      </DialogTrigger>
      <DialogContent className="sm:max-w-[425px]">
        <DialogHeader>
          <DialogTitle>Edit profile</DialogTitle>
          <DialogDescription>
            Make changes to your profile here. Click save when you're done.
          </DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <DialogClose asChild>
            <Button>
              <Text>OK</Text>
            </Button>
          </DialogClose>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
  1. Error throws when dialog attempted to open

Expected behavior
The modal opens properly, without crashing, similar to the demo.

Screenshots

Screenshot 2024-05-07 at 6 34 51 AM

Platform (please complete the following information):

  • Type: iOS Simulator - iPhone 15 Pro
  • OS: iOS 17.2

Additional context
It seems odd that AlertDialog works fine. I do have the PortalHost component in the top level _layout.tsx file, from the base template:

  return (
    <ThemeProvider value={isDarkColorScheme ? DARK_THEME : LIGHT_THEME}>
      <StatusBar style={isDarkColorScheme ? 'light' : 'dark'} />
      <Stack>
        <Stack.Screen
          name='index'
          options={{
            title: 'Starter Base',
            headerRight: () => <ThemeToggle />,
          }}
        />
      </Stack>
      <PortalHost />
    </ThemeProvider>
  );
@MikeSchlosser16 MikeSchlosser16 added the bug Something isn't working label May 7, 2024
@MikeSchlosser16 MikeSchlosser16 changed the title [ BUG ] Dialog not working as epxected [ BUG ] Dialog not working as expected - crashes when open around DialogContent May 7, 2024
@mrzachnugent
Copy link
Owner

mrzachnugent commented May 7, 2024

Edit: This issue is caused because a component is trying to import an Icon that you are not yet exporting from the ~/components/Icons file.

To fix this issue:,

  • Find the component that is importing an icon that doesn't exist. Your IDE should have a red squiggly line under the Icon name in its import statement.
  • Go to the ~/components/Icons file
  • Import the missing icon(s) from lucide-react-native
  • For each newly imported icon, call the interopIcon and pass it the icon
  • Export the Icon at the end of the file.

Hey @MikeSchlosser16 Thanks for bringing this up.

To fix this, you have to import, interop, then export the X icon from the ~/components/Icons:

import { Info, LucideIcon, MoonStar, Sun, X } from 'lucide-react-native';
import { cssInterop } from 'nativewind';

function interopIcon(icon: LucideIcon) {
  cssInterop(icon, {
    className: {
      target: 'style',
      nativeStyleToProp: {
        color: true,
        opacity: true,
      },
    },
  });
}

interopIcon(Info);
interopIcon(MoonStar);
interopIcon(Sun);
interopIcon(X);

export { Info, MoonStar, Sun, X };

For Futre Implementation
This issue also occurs in other components. In order to fix this issue, the Cli will add a file for each icon. This way I can easily add icons when components require them. I will also move them to the lib folder.

lib
│
└───Icons
│   │   interopIcon.ts
│   │   Info.tsx
│   │   MoonStar.tsx
│   │   Sun.tsx
│   │   X.tsx

@MikeSchlosser16
Copy link
Author

MikeSchlosser16 commented May 7, 2024

Thanks @mrzachnugent - I can confirm this resolved it for me using

import { Info, LucideIcon, MoonStar, Plus, Sun, X } from "lucide-react-native";
import { cssInterop } from "nativewind";

function interopIcon(icon: LucideIcon) {
  cssInterop(icon, {
    className: {
      target: "style",
      nativeStyleToProp: {
        color: true,
        opacity: true,
      },
    },
  });
}

interopIcon(Info);
interopIcon(MoonStar);
interopIcon(Sun);
interopIcon(Plus);
interopIcon(X);

export { Info, MoonStar, Plus, Sun, X };

Appreciate your prompt response! I'll be on the look out going forward but think your future state solution makes sense.

@GeoXhacker
Copy link

I was getting that error every time I tried to use Select, DropDownMenu, Dialog. And @mrzachnugent response fixes it.
To break down @mrzachnugent fix for others that might face the same issue before the Bug fix update.

  1. Locate the Icons file in ~/components
  2. Find out the lucide icons that the component i.e Select uses by checking the related ~/components/ui/select.ts
  3. import these icons in the Icon.ts file
  4. Add a complementary interopIcon(IconName) statement for each icon
  5. Add each iconName to the exports

import { Info, LucideIcon, MoonStar, Plus, Sun, X, ...IconNames } from "lucide-react-native";
import { cssInterop } from "nativewind";

function interopIcon(icon: LucideIcon) {
cssInterop(icon, {
className: {
target: "style",
nativeStyleToProp: {
color: true,
opacity: true,
},
},
});
}

interopIcon(Info);
interopIcon(MoonStar);
interopIcon(Sun);
interopIcon(Plus);
interopIcon(X);
interopIcon(IconName);
interopIcon(IconName);
interopIcon(IconName);

export { Info, MoonStar, Plus, Sun, X, ...IconNames };

Thank you for the fix @mrzachnugent
Thank you bringing this up @MikeSchlosser16

@mrzachnugent mrzachnugent changed the title [ BUG ] Dialog not working as expected - crashes when open around DialogContent [ BUG ] Error: Element type is invalid: expected a string May 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants