I am importing a third party script into my react application. The third party script is for a chatbot application built with botpress v12. I have made a react component as chatbot and implemented them in the parent page. But the problem is that, this bot is called only in single page or say route, but it is coming in every route. Yes might be because it gets appended in the body of the html, but I need it only in single page and whenever I navigate to another route the chatbot should not be rendered. this is my implementation example.
const BotpressChatbot = () => {
useEffect(() => {
const script = document.createElement('script');
const user = {`enter code here`
user_profile: getUserFromSession()?.profile.name,
oidc_User: sessionStorage.getItem(
`${SESSION_OIDC_TOKEN_KEY}:${AUTHORITY}:${CLIENT}`,
),
};
var my_data = JSON.stringify(user);
script.src =
'https://dev.bot.ask.speciphic.ai/assets/modules/channel-web/inject.js';
script.addEventListener('load', () => {
try {
let config = {
host: 'https://dev.bot.ask.speciphic.ai',
botId: 'jllask',
exposeStore: false,
startNewConvoOnTimeout: true,
useSessionStorage: true,
enableTranscriptDownload: false,
composerPlaceholder: 'Reply to JLL Ask',
enableConversationDeletion: true,
disableNotificationSound: false,
extraStylesheet:
'https://dev.bot.ask.speciphic.ai/assets/modules/channel-web/jllAsk.css',
};
window.botpressWebChat.init(config);
window.addEventListener('message', function (event) {
if (event.data.name && event.data.name == 'webchatReady') {
window.botpressWebChat.sendEvent({
type: 'proactive-trigger',
channel: 'web',
payload: { text: my_data },
});
} else if (
event.data.payload &&
event.data.payload.type == 'session_reset'
) {
window.botpressWebChat.sendEvent({
type: 'proactive-trigger',
channel: 'web',
payload: { text: my_data },
});
}
});
} catch (e) {
console.log('error in Botpress.jsx', e);
}
});
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, []);
return <></>;
};
export default BotpressChatbot;
in the return statement
return () => {
document.body.removeChild(script);
};
if I make the changes like
document.body.removeChild(document.getElementById('bp-web-widget'))
then it works fine, it gets removed from the other routes, and when navigating back to main page the chatbot renders again, but the problem is the script keeps on adding in the body again and again. the way the parent page has been implemented, it renders many times, lots of useEffects are there for the page to work, where it searches and do some operation. Chatbot is a different thing, not related to the working of its parent page. but needed in that page only.
It seems like the issue is that the chatbot script is being appended to the body multiple times when the parent page renders multiple times. This behavior can occur if the parent page has multiple useEffect hooks that run when the component mounts or updates. To ensure that the chatbot script is only appended once, you can modify the implementation as follows:
Separate the logic to load the chatbot script into its own useEffect hook with an empty dependency array. This will ensure that the chatbot script is only loaded once when the component mounts.
Move the logic to remove the chatbot script from the body to the cleanup function returned by the useEffect hook that loads the script. This way, when the component unmounts, the script will be removed from the body.
Here's the updated implementation:
By making these changes, the chatbot script should be loaded only once when the component mounts, and it will be removed from the body when the component unmounts. This should prevent the script from being appended multiple times and avoid the chatbot being rendered on other routes/pages.