In react Tippy I cannot make work some properties of tippy. I want allowHTML in Tippy.
Here is my code:
<Tippy
// content={<div dangerouslySetInnerHTML={{__html: tooltip}} />}
content={tooltip}
delay={100}
hideOnClick={false}
allowHTML={true}
>
...some other code here
</Tippy>
The commented code does what I would like to see. If the content contains html then it renders the content properly. I have found the solution here: https://github.com/atomiks/tippyjs-react/issues/94#issuecomment-498100958
However, I would like to use the own properties of tippy.
allowHTML does not work while delay and hideOnClick work.
It seems like the properties with "R" (see attached picture) do not seem to work and I cannot figure out how to use them in react and could not find in documentation either.
Tippy properties V6.x
Source: https://atomiks.github.io/tippyjs/v6/all-props/
My main issue with dangerouslySetInnerHTML was XSS vulnerability. That's why I wanted to use own property of tippyjs, the innerHTML. Because I though it handles XSS vulnerability but after reading the documentation again, more carefully, I realized it requires sanitizing data as well.
So I just go with dangerouslySetInnerHTML and sanitize my data before using it.
Here is my code:
import Tippy from '#tippy.js/react';
import dompurify from 'dompurify';
import React from 'react';
const PropertyLabel = ({ label, tooltip }) => {
const sanitizedTooltip = dompurify.sanitize(tooltip);
return (
<Tippy
content={<div dangerouslySetInnerHTML={{ __html: sanitizedTooltip }} />}
delay={100}
>
...some other code here
</Tippy>
);
};
Here are the sources that I used to implement dompurify:
https://pragmaticwebsecurity.com/articles/spasecurity/react-xss-part2.html
https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml:~:text=class%20attribute%20instead.-,dangerouslySetInnerHTML,-dangerouslySetInnerHTML%20is%20React%E2%80%99s
https://www.npmjs.com/package/dompurify
I know it does not solve the problem of using properties of Tippy marked with an "R" in React, but this single solution works instead of "allowHTML" property.
Related
I am trying to create a react component that has the class name as props being passed,
I have managed sending the props part successfully, however when I try to set the scss for the updated class name, I could not find a way to fix that, all of your input is appreciated.
Code of the component
Code of injecting the custom style class
Styles of the Variation
Output
Output of the Variation Class
Output of the Stylesheet
not sure what I am missing to connect all of them.
Thanks in advance.
As mentioned by Phil, your SCSS should be using &.secondary as the selector.
As for the difference in your scss class IDs and them not matching when you pass ${variant} to the className, your issue is that you are passing a raw string as the variant to the className and are using CSS modules for your SCSS (this is what handles namespacing them/adding the unique characters). To fix this, you need to use the imported style rather than a raw string for the className.
The way I usually address this is with an enum as the prop for different variants, or if there are only two a boolean, and then apply the imported style accordingly. A quick example of this, using your code would be:
const SectionTitle: FC<SectionTitleProps> = ({ title, isSecondary = false }) => (
<h3
className={`${styles.SectionTitle}${isSecondary ? styles.secondary : ''}`}
...
>
...
</h3>
);
I also find the classnames library helpful for this. It allows you to achieve the above with something I find a bit more readable, such as:
<h3
className={classNames(styles.SectionTitle, { [styles.secondary]: isSecondary } )}
...
>
...
</h3>
EDIT: Also including an example using classnames with an enum for different variants:
enum TitleVarient {
Default,
Secondary,
Accent,
}
const SectionTitle: FC<SectionTitleProps> = ({
title,
variant = TitleVarient.Default,
}) => (
<h3
className={classNames(styles.SectionTitle, {
[styles.secondary]: variant === TitleVarient.Secondary,
[styles.accent]: variant === TitleVarient.Accent,
})}
...
>
...
</h3>
);
Currently I'm using Next.js with Next-i18next for I18N, but I understand that the React/i18next implementation is basically the same.
The problem I'm having is that I need to interpolate a next Link component inside some translation text, but depending on the language (English vs German), the order of the text and the link would change.
For instance the text I'm struggling with is: 'Accept data policy' vs 'Datenschutzerklärung akzeptieren'
As of the moment I have a quick fix by creating two values in the translation JSON files for the text and the link and then swapping the position based on the current language. Obviously this is not a sustainable solution. I have tried to utilise the 'Trans' component but this is showing some unexpected behaviour where the translation only kicks in after the page is refreshed, otherwise you see the text inside the Trans component.
example:
function LinkText({ href, children}) {
return <Link to={href || ''}>{children}</Link>;
}
return (
<Trans i18nKey="sentence">
text before link
<LinkText href="/data-policy">{t("dataPolicy")}</LinkText>
text after link
</Trans>
);
and the JSON in question:
{
"sentence": "agree to our <1><0/></1>",
"dataPolicy": "data policy"
}
Here's a link to CodeSandbox I made to replicate the problem with in React: link
(P.S The implementation of i18next doesn't seem to effectively swap out the languages in Codesandbox at the moment, but I included it as the code is there for a MWE)
Thanks in advance for your help, this has been driving me insane.
You had few missing parts,
Your i18next config was lack of a way to fetch the locale files, I've added i18next-http-backend.
You should use Trans component to inject the link to the sentence.
Your locale json should look like this:
{
"sentence": "Accept <0>data policy</0>"
}
// TranslatedLink.js
import React from 'react';
import { useTranslation, Trans } from 'react-i18next';
import { Link } from 'react-router-dom';
function LinkText({ href, children }) {
return <Link to={href || ''}>{children}</Link>;
}
export default function TranslatedLink() {
const { t } = useTranslation(['common']);
return (
<div style={{ padding: 50 }}>
<Trans i18nKey="sentence" t={t} components={[<LinkText href="/data-policy" />]} />
</div>
);
}
A working example: https://codesandbox.io/s/react-i18n-interpolation-issue-forked-ck8l4
I have some data in an object that I'm iterating through, and I'm pulling a property (string) from this object to render to the screen.
The object looks like this:
`object: { id: 1, sample: 'To learn all about React, click here https://en.wikipedia.org/wiki/React_(JavaScript_library)' }`
I did lots of research and a lot of the answers pointed to using the Linkify plugin. I set up the Linkify plugin like so:
<Linkify>{sample}</Linkify>
This works good but I'm wondering if I'm able to modify the string so that I'm not displaying the actual address and instead, could I assign the address to the word 'here'. For example:
'To learn all about React, click `here`'.
Is this possible with the Linkify plugin or do I have to do something different?
You can try parsing the string to fetch the url from it. and then use the url as the value to the href attribute in a tag./
To fetch the url you could use regex.
(https?:\/\/\S+)|([a-z]+\.[a-z]+(?:\/\S+)?)
I tried using the regex to parse your string and it totally works.
I have taken this regex from here https://stackoverflow.com/a/39944457/10100750. You could see the link to know about this regex further.
You can implement this with react as well. Create a link component, that accepts 2 props. {url} and {link}.
hyperLink.js
import React from 'react'
export default ({ text, link }) =>{
return(
<a href={link}> {text} </a>
)
}
Then import into your index your index.js
import Hyperlink from './hyperLink'
<div>
To learn more about react click <Hyperlink link={#} text="here">
</div>
I have used a react-video component in my reactjs web application and it's working with a default source link, but when I'm using my video as a source, nothing happens.
I have searched a lot, read the documentation about react-video component, but could not solve the problem.
import {Player} from 'video-react';
<div className = 'video-container'>
<Player
playsInline
fluid={false}
src="https://media.w3.org/2010/05/sintel/trailer_hd.mp4"
width={600}
height={300}/>
</div>
I expect the new source to be working without any issues, but it never starts playing.
#Dato.Beriashvili, I have faced similar issues in default html video API, whenever i change src by anymeans video was not updated. so i have done below which fixed my issue.
useEffect(() => {
const myVideo= innerDoc.querySelector('#videoPlayer');
const mySource = innerDoc.querySelector('#source');
if (mySource && myVideo) {
mySource.setAttribute('src', videoUrl);
myVideo.load();
}
}, [videoUrl]);
whenever url changed, i'm manually loading it.
I have a string like < b >hi< /b >. I have to render it as "hi". Can someone let me know an equivalent thing like innerHTML in Angular that I can use in React?
you can try dangerouslySetInnerHTML with the enclosing tag:
<div dangerouslySetInnerHTML={{ __html: yourhtml }} />
According to official React docs
dangerouslySetInnerHTML is React’s replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack. So, you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key, to remind yourself that it’s dangerous. For example:
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
To avoid the potential security vulnerabilities (such as XSS attacks) that are present when using dangerouslySetInnerHTML, you can do the following:
First use DOMPurify to clean the HTML.
import DOMPurify from 'dompurify';
let clean = DOMPurify.sanitize(dirtyHtmlString, {USE_PROFILES: {html: true}});
Then it can be rendered using react-render-html as Salman Lone said:
import renderHTML from 'react-render-html';
<div>
{renderHTML(clean)}
</div>
in my case, I used following pacakge.
react-render-html
According to the website "https://reactjs.org/docs/dom-elements.html" you should use dangerouslySetInnerHTML in order to avoid cross-site scripting (XSS) attacks. However, if you are controlling the string that you want to render then that may not be necessary. If you wish to render HTML this way then as the above website explains, you may do so in this way:
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
I personally do not like the dangerouslySetInnerHTML method (mostly because it has the word dangerous and that scares me). I cannot say if the next method is better, safer, faster etc but I like it much more. The second method that you can use is to render the HTML with useRef.
An example of this method is:
import React, {useRef, useEffect} from 'react'
export default function Example() {
const aRef = useRef()
const content = '<p style="color:red">hello</p><h1>world</h1>'
useEffect(()=>{
if(aRef==null)return
aRef.current.innerHTML = content
},[aRef, content])
return <div ref={aRef}/>
}
I forgot to do testing for setting class, id, ref, values etc via string.
If someone wants to add to this answer, please add examples for every React operation like I have done with style.