lucide icon indicating copy to clipboard operation
lucide copied to clipboard

Next.js 13+ Dynamic imports cause client side re-render.

Open remainstheday opened this issue 1 year ago • 6 comments

Package

  • [ ] lucide
  • [ ] lucide-angular
  • [ ] lucide-flutter
  • [ ] lucide-preact
  • [X] lucide-react
  • [ ] lucide-react-native
  • [ ] lucide-solid
  • [ ] lucide-svelte
  • [ ] lucide-vue
  • [ ] lucide-vue-next
  • [ ] Figma plugin
  • [ ] source/main
  • [ ] other/not relevant

Version

0.263.1

Browser

  • [X] Chrome/Chromium
  • [ ] Firefox
  • [ ] Safari
  • [ ] Edge
  • [ ] iOS Safari
  • [ ] Opera
  • [ ] Other/not relevant

Operating system

  • [ ] Windows
  • [ ] Linux
  • [X] macOS
  • [ ] Other/not relevant

Description

Following the documentation for dynamic imports in nextjs causes all icons to flash with a client side re-render. CleanShot 2023-12-14 at 17 39 57

Steps to reproduce

  • npm install lucide-react inside a Next 13+ application
  • follow the example for creating a dynamic import https://lucide.dev/guide/packages/lucide-react#nextjs-example
  • use the dynamic <Icon /> inside a "use client" component
  • navigate away and/or trigger a useState() event
  • observe the re-render of <Icon />

Checklist

  • [X] I have searched if someone has submitted a similar issue before and there weren't any. (Please make sure to also search closed issues, as this issue might already have been resolved.)

remainstheday avatar Dec 15 '23 02:12 remainstheday

Dynamic icons are just not a good idea, we should consider removing it.

jguddas avatar Dec 15 '23 08:12 jguddas

I was able to fix this issue by going back to explicitly importing each icon by name.

remainstheday avatar Dec 16 '23 23:12 remainstheday

@jguddas yeah seems everyone is misusing this. This should be done with normal imports not with dynamicImports.

ericfennis avatar Dec 18 '23 14:12 ericfennis

@remainstheday yeah that how you should do it. Dynamic imports are only example using CMS systems.

ericfennis avatar Dec 18 '23 14:12 ericfennis

"I was able to solve it by memoizing the component." ` import dynamic from 'next/dynamic'; import { memo } from 'react'; import { LucideProps } from 'lucide-react'; import dynamicIconImports from 'lucide-react/dynamicIconImports';

interface IconProps extends LucideProps { name: keyof typeof dynamicIconImports; }

const Icon = memo(({ name, ...props }: IconProps) => { const LucideIcon = dynamic(dynamicIconImports[name]);

return <LucideIcon {...props} />; });

export default Icon;

`

HOJOON07 avatar Apr 17 '24 17:04 HOJOON07

"I was able to solve it by memoizing the component." ` import dynamic from 'next/dynamic'; import { memo } from 'react'; import { LucideProps } from 'lucide-react'; import dynamicIconImports from 'lucide-react/dynamicIconImports';

interface IconProps extends LucideProps { name: keyof typeof dynamicIconImports; }

const Icon = memo(({ name, ...props }: IconProps) => { const LucideIcon = dynamic(dynamicIconImports[name]);

return <LucideIcon {...props} />; });

export default Icon;

`

this helped me!! thank youuu

katieagne avatar May 03 '24 22:05 katieagne