I am trying to add a button tag between a text when a pattern is found in react, this is done inside the dangerouslySetInnerHTML attribute. The onClick only works with alert() and console.log(), it doesn't work when I passed a function to it. What am I missing?
export const detectHashTagPattern = (text) => {
if(!text) return '';
let pattern = /This is a follow-up to your previous request #[0-9]+/gi;
let hashTagPattern = /#[0-9]+/;
text = text.replace(pattern, (res) => {
return res.replace(hashTagPattern, `<button onClick={}>${hashTagPattern.exec(res)}</button>`);
});
return text;
};
Well you could change the algorithm like the following:
function clickHandler() {
console.log("do something");
}
window.clickHandler = clickHandler;
export const detectHashTagPattern = (text) => {
if (!text) return "";
let pattern = /This is a follow-up to your previous request #[0-9]+/gi;
let hashTagPattern = /#[0-9]+/;
text = text.replace(pattern, (res) => {
return res.replace(
hashTagPattern,
// use window.<fct>()
`<button onClick="window.${window.clickHandler.name}()">${hashTagPattern.exec(
res
)}</button>`
);
});
return text;
};
You shouldn't go with this approach, as it might have other issues with the rendering in your application (depends what you're doing in the handler).
A better approach would be like this:
const splitSubject = (text) => {
if (!text) {
return [""];
}
let pattern = /This is a follow-up to your previous request #[0-9]+/gi;
if (!pattern.test(text)) {
return [text];
}
let hashTagPattern = /#[0-9]+/;
let result = text.search(hashTagPattern);
return [text.slice(0, result), text.slice(result), text.slice(result + 1)];
};
const Subject = ({ subject, handler }) => {
const splitted = splitSubject(subject);
let content = null;
if (splitted.length === 1) {
content = <span>{splitted[0]}</span>;
} else {
let [info, cmd, reqReference] = splitted;
content = (
<>
<span>{info}</span>
<button onClick={() => handler?.(reqReference)}>{cmd}</button>
</>
);
}
return <p>{content}</p>;
};
export default function App() {
const requestHandler = (num) => {
console.log(`click on '${num}'`);
};
return (
<div>
<Subject
handler={requestHandler}
subject="This is a follow-up to your previous request #9"
/>
<Subject handler={requestHandler} subject="Not matching subject" />
</div>
);
}