react-fontawesome
react-fontawesome copied to clipboard
Bug: Defining icons from strings in React works, but there is always the 'Could not find icon' error message
This is a direct copy of this bug report by @Stephcraft
Describe the bug When you do this for example:
<Icon icon={['fas', 'gamepad']}/>
and I even add every icon to the font awesome react library object. I've tried two different ways, same outcome:
import { library } from "../../node_modules/@fortawesome/fontawesome-svg-core"
import { fas } from '@fortawesome/free-solid-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons'
import { fab } from '@fortawesome/free-brands-svg-icons'
library.add(fab)
library.add(fas)
library.add(far)
import { library } from "../../node_modules/@fortawesome/fontawesome-svg-core"
import * as FontAwesomeSolidIcons from '@fortawesome/free-solid-svg-icons'
import * as FontAwesomeRegularIcons from '@fortawesome/free-regular-svg-icons'
import * as FontAwesomeBrandsIcons from '@fortawesome/free-brands-svg-icons'
const geticonList = (module) => Object
.keys(module)
.filter(key => key !== "fas" && key !== "far" && key !== "fab" && key !== "prefix" )
.map(icon => module[icon])
library.add(...[
...geticonList(FontAwesomeRegularIcons),
...geticonList(FontAwesomeSolidIcons),
...geticonList(FontAwesomeBrandsIcons)
])
The icons do display, but the error message is still present:
Could not find icon { prefix: 'fas', iconName: 'gamepad' }
Reproducible test case
Steps to reproduce:
- Access https://codesandbox.io/s/zen-chihiro-ku0do2?file=/pages/index.js
- Open the preview in a new tab (or open this URL to go directly: https://ku0do2.sse.codesandbox.io/ )
- Open Chrome DevTools,
CTRL+SHIFT+P
/CMD+SHIFT+P
, type "Disable Javascript" and press enter - Refresh the page
- You'll notice the 'search' icon doesn't render
Expected behavior Expected the search icon to render server side and be in the HTML
Desktop (please complete the following information):
- Browser: Chrome
- Version: 105
(Although the issue is with SSR, not the browser 😉 )
Additional context
If you change the line
import { config, library } from "@fortawesome/fontawesome-svg-core";
to
const { config, library } = require("@fortawesome/fontawesome-svg-core");
(and restart the server on codesandbox)
you'll notice it start server side rendering....
The library
is a singleton. So I'm betting that there is something going on with the SSR side of things that results in that singleton being instantiated multiple times.
This will take some investigation into how Next.js works. The workaround for this would be to explicitly reference icons instead of using the Library object.
import { faGamepad } from '@fortawesome/free-solid-svg-icons'
<Icon icon={faGamepad} />
The
library
is a singleton. So I'm betting that there is something going on with the SSR side of things that results in that singleton being instantiated multiple times.
Well, yes... But I'd probably point out that the SSR (NextJS) might be using the ES version and somehow the react-awesome might be using the non-ES version which might lead to inconsistencies at the singleton value...
FWIW I've been able to solve this in testing bu adding the library to a client side component like below
"use client"
export default function SMButton({ sm }: { sm: SocialMedia }) {
console.log(sm.icon)
library.add(faTwitter)
const icon = findIconDefinition({
prefix: sm.icon[0],
iconName: sm.icon[1],
})
console.log(icon)
return (
<div>
<Link
href={sm.link}
className="text-white transition ease-in-out duration-200"
onClick={(): void => trackGoal(sm.tracking, 0)}
onMouseEnter={(event): void => {
event.currentTarget.style.color = sm.color
// event.currentTarget.style.transform = 'scale(1.2)'
}}
onMouseLeave={(event): void => {
event.currentTarget.style.color = ''
// event.currentTarget.style.transform = 'scale(1)'
}}
>
<FontAwesomeIcon
icon={icon}
size="1x"
className="mx-1 transform-gpu transition duration-200 ease-in-out"
/>
</Link>
</div>
)
}
Also getting this in NextJs on client side components. They work as expected in server side components, but I think it fails in client side as it doesn't see the config.
It is throwing error Could not find icon { prefix: 'far', iconName: 'home' }
I am using the @fortawesome/react-fontawesome
to render the icons as recomened in the FA setup.
FA is configured like this in the new layout.tsx file.
import { config, library } from '@fortawesome/fontawesome-svg-core'
import { fas } from '@fortawesome/pro-solid-svg-icons';
import { far } from '@fortawesome/pro-regular-svg-icons';
config.autoAddCss = false;
library.add(fas, far, fal);
The using a icon like so <FontAwesomeIcon icon={['far', 'home]} />
I have tried dumping all the imports into a client side component - that fixes it, but then its looking like a lot of bloat from the mulitple imports!
Doing the const { config, library } = require("@fortawesome/fontawesome-svg-core");
hack around does not fix this