You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FontAwesome与React服务端渲染下dom.watch()图标不显示问题求助

Fixing FortAwesome dom.watch() Not Replacing Tags in SSR Menus (react-metismenu)

Got it, let's tackle this problem step by step— I've run into similar SSR-related icon issues with Font Awesome before, so here are actionable solutions tailored to your setup:

1. Manually Trigger dom.watch() After Client Hydration

The core issue here is that dom.watch() by default listens for newly added DOM elements, but your SSR-rendered <i> tags already exist in the DOM when the client loads. To fix this, we just need to manually run dom.watch() once the client has hydrated the component.

Add this to your menu component (or a parent component that wraps the menu):

import { dom } from '@fortawesome/fontawesome-svg-core';
import { useEffect } from 'react';

function YourMenuWrapper() {
  useEffect(() => {
    // This will scan the entire DOM for <i> tags and convert them to SVG
    dom.watch();
  }, []); // Empty dependency array ensures this runs only once after mount

  return <YourMetisMenuComponent />;
}

This is the quickest fix and should resolve the icon display issue for most SSR setups.

2. Custom Icon Renderer for react-metismenu

If the first solution doesn't work (or you want more control), you can leverage react-metismenu's custom rendering capabilities to handle icons directly, without relying on <i> tags. Even though you can't use <FortAwesomeIcon>, you can manually convert icon classes to SVG using Font Awesome's core utilities:

First, make sure you've added your required icons to the Font Awesome library:

import { library } from '@fortawesome/fontawesome-svg-core';
import { faHome, faUsers, faSettings } from '@fortawesome/free-solid-svg-icons';

// Add all icons your menu uses here
library.add(faHome, faUsers, faSettings);

Then create a custom icon renderer function and pass it to react-metismenu (check react-metismenu's docs for the exact prop name— it's usually something like iconRenderer):

import { dom } from '@fortawesome/fontawesome-svg-core';
import React from 'react';

const customIconRenderer = (iconClass) => {
  // Create a temporary <i> element with the icon class
  const tempIcon = document.createElement('i');
  tempIcon.className = iconClass;

  // Convert it to an SVG element using Font Awesome
  const svgElement = dom.i2svg(tempIcon);

  // Convert the native SVG element to a React element
  return React.createElement(
    svgElement.tagName,
    {
      ...Object.fromEntries(svgElement.attributes),
      className: svgElement.className,
      dangerouslySetInnerHTML: { __html: svgElement.innerHTML }
    }
  );
};

// Use it in your menu component
<MetisMenu
  iconRenderer={customIconRenderer}
  // Your other menu props here
/>

This bypasses the need for dom.watch() entirely by rendering SVG directly from the start.

3. Pre-Process Icons on the Server

For a more robust SSR solution, you can convert <i> tags to SVG on the server before sending the HTML to the client. This ensures the client receives fully rendered SVG icons right away:

In your server-side rendering logic (e.g., Next.js getServerSideProps, or Express render function):

import { dom, library } from '@fortawesome/fontawesome-svg-core';
import { faHome, faUsers } from '@fortawesome/free-solid-svg-icons';
import ReactDOMServer from 'react-dom/server';

// Add your icons to the library first
library.add(faHome, faUsers);

// Render your menu component to HTML string
const menuHtml = ReactDOMServer.renderToString(<YourMetisMenuComponent />);

// Convert all <i> tags in the HTML to SVG
const processedMenuHtml = dom.i2svg(menuHtml);

// Pass the processed HTML to your client component
// (How you do this depends on your SSR framework— e.g., in Next.js, pass it as a prop)

Then in your client component, render the processed HTML using dangerouslySetInnerHTML:

function ClientMenu({ processedMenuHtml }) {
  return <div dangerouslySetInnerHTML={{ __html: processedMenuHtml }} />;
}

Final Notes

Start with solution 1—it's the simplest and most likely to work for your case. If you still run into issues, move to solution 2 for more control over icon rendering. Solution 3 is best for apps where you want to minimize client-side processing.

内容的提问来源于stack exchange,提问作者Ezaos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 09:22:31