How do I apply a URL in a string? - reactjs

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>

Related

#tippy.js/react allowHTML

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.

how do I interpolate a Link component in Next-i18next / React i18next that changes position in the text

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

How to setup React Router <Link> inside a Datatables.net Cell?

I have a datatables table (https://datatables.net) initialized like this:
$('#example').DataTable({
data: data,
columns: [{
title: "Database ID",
data: 'database_id',
render: function (data, type, row) {
return '<NavLink to="/shop">'+ data +'</NavLink>';
}
}]
});
The NavLink that i have in the code is supposed to render a database cell as a clickable link because of React-Router (This whole function is inside a React component), but the link is not rendering when i run the code.
What i ultimately want is the ability to click on a database cell that will take me to another component by routing into a link like "/shop/id" but i am stuck in it for a long time. Help!
I was facing the same issue and below solution is working for me.
You can directly add anchor tag with href to the path where you want to route upon on the click. But, it will reload your application.
To avoid reloading of the application, try below solution.
When you're initializing the columns dynamically, you can add below code for the column where you want to have a link.
fnCreatedCell: (nTd, data) => ReactDOM.render(
<a
onClick={() => handletableclick(data, props)}>
{data}
</a>, nTd)
Add handletableclick() function/method in your file to handle click event and programmatically through history push the path where you want to route upon the click
function handletableclick(data, props) {
props.history.push("/pathToRoute=" + data);
}
Also,in above code to access history from props, you will need to enclose your component with withRouter
like below :
export default withRouter(YourComponentName);

Create Html from React Component including Style

I have a simple react component in which using ref I am getting the div but I have to generate a html includes styling as well. So I can pass this html to PDF generation backend server.
pdfRef(elem){
console.log(elem);
//<div><span>dataPDF</span> </div>
}
render() {
return (
<div ref={(elem) => this.pdfRef(elem)} className="SomeCssClass">
<span >dataPDF</span>
</div>
);
}
}
[Edit]
When I try to print the div via ref, the elements are printed with class name. But when I send this string to pdf service, since only html element is sent and class name without the actual css , the pdf is generated without style.
is there any way to generate html with css as as string so further it can be send to pdf service. Hope the question is clear
Any pointers?
The server.js script in react-dom lets you render a React component to static html string. You can require it in your code like:
const ReactDOMServer = require('react-dom/server');
Or using ES6 syntax:
import ReactDomServer from 'react-dom/server'
After this you can render your component to HTML string using the ReactDomServer.renderToString or ReactDomServer.renderToStaticMarkup functions as follows:
const htmlStr = ReactDomServer.renderToStaticMarkup(<MyComponent prop1={'value1'} />);
This looks almost exactly like ReactDom.render, except that it doesn't need the second parameter of dom node to render at, and the html string is returned. Additionally this method can be used on both client and server side. For your generate-pdf use case renderToStaticMarkup would suffice. If required check the documentation at following link for subtle difference between the two methods mentioned above: https://reactjs.org/docs/react-dom-server.html

React - pass props/state to rendered HTML string?

In my React app, I have stored a text template as an HTML string on the server which is passed up to the client to be rendered. Is it possible to render this HTML string in such a way that it can access it's parent component state/props? I've tried using dangerouslySetInnerHTML and ReactDOMServer.renderToString(), both of which render the string as HTML, but render {props.text} as a literal string, rather than a reference to the component's props.
For example, on the server I have stored:
<div>Welcome to my app</div>
<div>{props.message}</div>
<div>Have fun</div>
And the component
import React from "react"
import { connect } from "react-redux"
const mapStateToProps = (state) => {
return { state }
},
WelomeBody = (props) => {
return (
<div dangerouslySetInnerHTML={{"__html": props.state.welcomeMessageBody}} />
)
}
export default connect(mapStateToProps, null)(WelomeBody)
but this results in:
Welcome to my app
{props.message}
Have fun
Is there a way that this can be rendered so as to access the value of props.message, rather than just rendering it literally?
If what you have in mind is to send down a React component (in JSX syntax) from your server to your client and have the client somehow rehydrate/compile it into an actual, working component, this is not achievable that easily.
When you build and bundle your React app, only components that are statically referenced/imported in your application at compile time can be used at runtime on the browser.
So, in order to dynamically render a component from a template and embed variables into it, your choices are:
Render it into final HTML on your server, send down that HTML and have a simple React component perform dangerouslySetInnerHTML for it. But, like you've already observed, that content has to be the full HTML code, no templates, variables, JSX, etc. Everything is string and HTML at this point, no more processing.
Alternatively, send down a Markdown document and have a Markdown component parse it into HTML and display it.
Create a sophisticated component that can receive a string, parse it, tokenize it, substitute values in it, etc. Essentially, create your own template-processing component that can read a template (the string sent down from your server) and embed the appropriate values into it.
A simple solution (to substitute values into a template) would be:
function Filler(props) {
let html = props.template;
Object.keys(props).forEach(key => {
if (key !== "template")
html = html.replace("{" + key + "}", props[key]);
});
return <div dangerouslySetInnerHTML={{__html: html}} />;
}
and use it like
<Filler template={"<h1>Hello, {firstname} {lastname}</h1>"} firstname="John" lastname="Doe" />
But again, this is far from a full-fledged actual React component.

Resources