Skip to main content

· 4 min read

In this article, we will guide you through the process of using dynamic React Icons in the Menu. This feature is especially useful when you need to render icons dynamically based on data received from an API.

You will have to create a helper component, DynamicIcon, to simplify this process. This component leverages Next.js's dynamic import feature to load icons on demand, thereby optimizing your application's performance.

Getting started

Before we dive into the implementation details, ensure that your project is set up and running. You should also have the react-icons package installed in your template. If you haven't already installed it yet, you can do so by running the following command:

pnpm install react-icons

Understanding the DynamicIcon component

The DynamicIcon component is designed for integrating dynamic icon rendering. It leverages Next.js's dynamic import feature from next/dynamic to load icons on demand. This helps to optimize your application's performance by only loading the icons that are required. This component is particularly useful for applications that need to render icons dynamically based on data received from an API.

  • Dynamic Imports with Next.js: Utilizes Next.js's dynamic function to import dynamically based on the component's props.
  • iconFamily prop: Determines the library from which to import the icon (e.g., fa for Font Awesome, fi for feather icons). This prop makes the component versatile allowing it to support multiple icon libraries with ease.
  • icon prop: Specifies the exact icon to be dynamically imported from the chosen library.
  • Fallback Icons: Provides a default fallback icon for each library to handle cases where the specified icon cannot be found. This feature ensures that your UI remains consistent and error-free, even when an icon is missing or incorrectly named.
  • Expandability: The DynamicIcon component is designed to be easily expandable. You can include as many icon libraries as you need by importing them and adding them to the Icons object with appropriate fallbacks.

How to make this work in the template

To use the DynamicIcon component, you need to follow these steps:

  1. Copy the DynamicIcon component code from the snippet below and paste it into a new file in your project, such as DynamicIcon.tsx/DynamicIcon.js respectively for TypeScript or JavaScript version in the src/components directory.

    // Next Imports
    import dynamic from 'next/dynamic'

    import { FaRegCircle } from 'react-icons/fa'
    import { FiCircle } from 'react-icons/fi'

    // React imports
    import type { IconBaseProps } from 'react-icons'

    type DynamicIconProps = {
    iconFamily: string
    icon: string
    }

    type IconsMapping = {
    [key: string]: React.ComponentType<IconBaseProps>
    }

    const DynamicIcon = ({ iconFamily, icon }: DynamicIconProps) => {
    const Icons: IconsMapping = {
    fa: dynamic(
    () =>
    import('react-icons/fa').then(mod => mod[icon]).then(e => (e === undefined ? FaRegCircle : e)) as Promise<
    React.ComponentType<IconBaseProps>
    >
    ),
    fi: dynamic(
    () =>
    import('react-icons/fi').then(mod => mod[icon]).then(e => (e === undefined ? FiCircle : e)) as Promise<
    React.ComponentType<IconBaseProps>
    >
    )
    }

    const Icon = iconFamily && icon ? Icons[iconFamily] : null

    return <>{Icon && <Icon />}</>
    }

    export default DynamicIcon
  2. Now you need to import the DynamicIcon component into src/components/GenerateMenu.tsx and use it like the following:

    - const icon = <i className={menuItem.icon} />
    + const icon = menuItem.icon && menuItem.iconFamily && (
    + <DynamicIcon iconFamily={menuItem.iconFamily} icon={menuItem.icon} />
    + )

    - const { children, ...rest } = subMenuItem
    + // eslint-disable-next-line @typescript-eslint/no-unused-vars
    + const { children, iconFamily, ...rest } = subMenuItem

    - <VerticalSubMenu key={index} {...rest} icon={icon}>
    + <VerticalSubMenu key={index} {...rest} icon={icon || undefined}>

    Add this before returning the VerticalMenuItem component:

    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const { iconFamily, ...rest } = menuItem
    - <VerticalMenuItem key={index} {...menuItem} href={href} icon={icon}>
    + <VerticalMenuItem key={index} {...rest} href={href} icon={icon || undefined}>
  3. Now update src/types/menuTypes.ts file, add iconFamily for VerticalMenuItemDataType and VerticalSubMenuDataType for TypeScript version only.

    export type VerticalMenuItemDataType = Omit<VerticalMenuItemProps, ...> & {
    ....
    iconFamily?: string
    }

    export type VerticalSubMenuDataType = Omit<VerticalSubMenuProps, ...> & {
    ...
    iconFamily?: string
    }
  4. That is it! You have successfully integrated the DynamicIcon component into your template. You can now dynamically render icons based on data received from an API.

tip

You can do the same for Horizontal Menu, to use dynamic icons.

tip

If you want to use a different library than react-icons, you can take the DynamicIcon component as a reference or ispiration and create your own component. All you need to figure out is how to dynamically import the icons from the library you are using like prop-types, etc.

· One min read

Search has been implemented in the full-version only. If you have started your project using the starter kit as per our suggestion, please follow the below steps in order to implement search functionality in your project.

Begin by installing kbar package which is related to search functionality

Run the appropriate command in your project's root directory based on your package manager:

pnpm install kbar
  1. Copy full-version/src/components/layout/shared/search folder from the full-version and paste it in your project's src/components/layout/shared folder.

  2. You have to create a searchData.ts/js file in your project's src/data/ folder. This file will contain the data that will be used for search.

  3. Import the <NavSearch /> component in src/components/layout/vertical/NavbarContent.tsx file and add after the <NavToggle /> component.

That's it. You have successfully implemented search functionality in your project.🥳🎉

· 2 min read

We are using Next.js API routes to fetch data from the database. You can find all the API routes in src/app/api folder. This makes our template API ready and you can use it with any backend.

How to remove Fake DB

However, you won't need fake DB if you are using real API. In this case please follow below steps to remove fake DB from the template.

  • If you are not using the fake DB then you can remove src/app/api/fake-db folder.

  • Remove imports related to fake DB.

    NOTE

    Now all (fake) API calls will result Module not found error, until you replace them with your own real API endpoints.

How to replace API endpoints

As fake DB is removed, and you are using real API, you can delete the whole folder src/app/api and replace it with your own API endpoints.

Make sure you've built the APIs in your backend and connected them to your database before you switch out the sample APIs with the real ones.

NOTE

If the structure of the data you receive from the API is different from the sample data, you will need to update the code in the components that use the data.

You can refer to the data structure in src/app/api/fake-db folder.

  • For example you want to fetch data from https://fakedata.example.com/ then you can create a file src/app/**/page.tsx and add following code:
// Component Imports
import Component from '@views/pages/component'

const getData = async () => {

const res = await fetch(`https://fakedata.example.com/`)

if (!res.ok) {
throw new Error('Failed to fetch page Data')
}

return res.json()
}

const ComponentPage = async () => {

const data = await getData()

return <Component data={data} />
}

export default ComponentPage

You can refer Next.js documentation for more information on data fetching.

· 2 min read

Vuexy admin provides internationalization for navigation only. There might be a time when you might want to translate any text in a page. Here's how you can achieve that:

  1. Make sure your have @formatjs/intl-localematcher, @types/negotiator (Typescript version only), and negotiator packages installed
  2. It is important to have locale defined in your path. For eg. http://localhost:3000/en/apps/chat where en is a locale which refers to the English language
  3. Create JSON files with language as their file names in locales depending on the languages you need. For example, we're using three languages English, French & Arabic
en.json
{
"helloWorld": "Hello World",
"text": {
"paragraph": "This is a paragraph"
},
"navigation": {
...
}
}
fr.json
{
"helloWorld": "Bonjour le monde",
"text": {
"paragraph": "C'est un paragraphe"
},
"navigation": {
...
}
}
ar.json
{
"helloWorld": "مرحبا بالعالم",
"text": {
"paragraph": "هذه فقرة"
},
"navigation": {
...
}
}
  1. Import getDictionary and type { locale } in the page where you want to translate the content
import { getDictionary } from '@/utils/get-dictionary'
import type { Locale } from '@configs/i18n'
  1. You can now initialize the getDictionary and pass the locale as a parameter. This will return a promise which you can use to get the dictionary
// Type Imports
import type { Locale } from '@configs/i18n'

// Util Imports
import { getDictionary } from '@/utils/get-dictionary'

const Component = async ({ params }: { params: { lang: Locale } }) => {

// getDictionary only called on the server side, calling it on the client side will throw an error
const dictionary = await getDictionary(params.lang)

return (
<>
<div>{dictionary.helloWorld}</div>
<div>{dictionary['text'].paragraph}</div>
</>
)
}

export default Component

That's it! You can now translate any text in your page.