Issue with BBCode image tag on React

21 Views Asked by At

I have such component which renders the BBCode image tag on my website on React:

Code:

BBCodeComponent.tsx:

import React from "react";
import ReactDOMServer from "react-dom/server";
import CustomTooltip from "./CustomTooltip";

const BBCodeComponent = ({content}) => {
    const parseBBCode = (text) => {
        return text
        .replace(/\[img=(.*?)\](.*?)\[\/img\]/g, (match, title, src) => {
            return ReactDOMServer.renderToString(<CustomTooltip msg={title}><img src={src} alt={title} /></CustomTooltip>);
        })
        .replace(/\[quote](.*?)\[\/quote\]/g, "<blockquote>$1</blockquote>");
    };

    return <div dangerouslySetInnerHTML={{__html: parseBBCode(content)}} />;
};

export default BBCodeComponent;

CustomTooltip.tsx:

import React from "react";
import {Tooltip} from "react-tippy";

export type Position =
  | "top"
  | "top-start"
  | "top-end"
  | "bottom"
  | "bottom-start"
  | "bottom-end"
  | "left"
  | "left-start"
  | "left-end"
  | "right"
  | "right-start"
  | "right-end";
export type Size = "small" | "regular" | "big";
export type Theme = "dark" | "light" | "transparent";

interface IToolTip {
    children: React.ReactNode;
    msg: string;
    pos?: Position, 
    tooltipSize?: Size, 
    tooltipTheme?: Theme
}

const CustomTooltip = ({children, msg, pos = "top", tooltipSize = "big", tooltipTheme = "light"} : IToolTip) => {
    return (
        <Tooltip title={msg} position={pos} size={tooltipSize} theme={tooltipTheme} followCursor={true}>{children}</Tooltip>
    );
};

export default CustomTooltip;

The issue is that it incorrectly renders the CustomTooltip component. It just renders the default browser tooltip instead of the react-tippy. Any ideas how to render it properly to display react-tippy image title?

1

There are 1 best solutions below

0
Hunter91151 On

Ok. I have fixed this issue by using useEffect and ReactDOM.render method:

Code:

import React, {useEffect} from "react";
import ReactDOM from "react-dom";
import CustomTooltip from "./CustomTooltip";

const BBCodeComponent = ({content}) => {
     useEffect(() => {
        const tooltipWrappers = document.querySelectorAll(".tooltip-wrapper");
        tooltipWrappers.forEach((wrapper) => {
            const title = wrapper.getAttribute("data-title");
            const src = wrapper.getAttribute("data-src");
            
            if (title && src) {
                const tooltipComponent = (
                    <CustomTooltip msg={title}><img src={src} alt={title} /></CustomTooltip>
                );
                ReactDOM.render(tooltipComponent, wrapper);
            }
        });
    }, [content]);

    const parseBBCode = (text) => {
        return text
        .replace(/\[img=(.*?)\](.*?)\[\/img\]/g, (match, title, src) => {
            return `<div class=\"tooltip-wrapper\" data-title=\"${title}\" data-src=\"${src}\"><img src=\"${src}\" alt=\"${title}\"></div>`;
        })
        .replace(/\[quote\](.*?)\[\/quote\]/g, "<blockquote>$1</blockquote>");
    };

    return <div dangerouslySetInnerHTML={{__html: parseBBCode(content)}} />;
};

export default BBCodeComponent;

I get all .tooltip-wrapper items by using document.querySelectorAll method. Then I use forEach loop to get title and src attributes. Finally, I create tooltip component and render it. It works well. The issue is resolved.