React - how to render HTML contained into a variable? - javascript

I am trying to create a dynamic link Component that transforms a string in a string with a html anchor.
What I want to obtain is a component that returns this output:
<p>Do you want to search?</p>
I am passing this object to the component
let phrase = {
text : 'Do you want to search?'
linktext : 'to search',
linkurl : 'http://google.com'
}
This is the component I tried but do not work and the html is rendered as a text
function InfoLink(props) {
const q = props.phrase;
const link = "<a href={q.linkurl} >{q.linktext}</a>";
const text = q.text.replace(q.linktext, link);
return (
<p>{text}</p>
);
}
Is there a way to have a html output from the component by using replace?

You can split the text, and output the split text along with a react component for the anchor:
let phrase = {
text : 'Do you want to search?',
linktext : 'to search',
linkurl : 'http://google.com'
}
function InfoLink(props) {
const q = props.phrase;
const link = <a href={q.linkurl}>{q.linktext}</a>;
const [part1, part2] = q.text.split(q.linktext);
return (
<p>{part1}{link}{part2}</p>
);
}
ReactDOM.render(<InfoLink phrase={phrase}/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

You can split your sentence in 3 parts:
text_before_link <a href={q.linkurl}> text_with_link </a> text_after_link
Where...
text_before_link = q.text.substr(0,q.text.indexOf(q.linktext));
text_with_link = q.linktext;
text_after_link = q.text.substr(q.text.indexOf(q.linktext)+q.linktext.length);
Something like that.

The variable link is a JSX Object and you are adding it to an string. So the result will be something like: Do you want [Object][Object]. To solve this problem, you should split the string you want to show and the object and return both.
export default function App (props){
const q = props.phrase;
const link = <a href={q.linkurl}>{q.linktext}</a>;
const text = q.text.split(q.linktext)[0];
return (
<p>{text}{link}</p>
);}
Hope this can help.

Related

How to access the data from data* attribute using JavaScript?

Scenario: When the user clicks on it, the data should be passed into someFunction().
<span id="someid" onClick={() => someFunction()} data-video-page="some data" class="dot" />`
I tried using getAttributes(), querySelector() methods until now to get the data from data attributes. But one of them are working, in fact they are returning none.
There is a React.js tag in your question, so I'll assume that this is for using data-set in React.js.
For React.js, this is how data-set can be used if you want to pass the data to some function on a click event. You can also visit the live demo here: stackblitz
const handleClick = (event) => {
// Your data is stored in event.currentTarget.dataset
// Here we get the data by destructuring it
// The name video-page need to change to videoPage for JS rules
const { videoPage } = event.currentTarget.dataset;
console.log(videoPage);
// Result printed: "your data"
// You can also run someFunction(videoPage) here
};
export default function App() {
return (
<button data-video-page="your data" onClick={handleClick}>
TEST
</button>
);
}
A working snippet
const someFunction = console.log;
function App() {
return (
<span id="someid"
onClick={(e) => {
const videoPage = event.target.dataset['videoPage'];
someFunction(videoPage)
}}
data-video-page="some data"
className="dot"
>
click me
</span>
)
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
The data* attribute can be accessed using the getAttribute() method.
Example 1:
var data = document.getAttribute('data*');
Example 2:
var element = document.querySelector('div');
var data = element.getAttribute('data');

ReactJS fetched html data manupilation

I have a mongodb database where I saved raw html in it. I have created a custom attribute in the html called kk-id to mention objects inside the html. I want to replace that particular html tag with an anchor tag.
I figured a way to do it using vanilla javascript, however I was wondering if there was a more efficient reactjs way to do it.
data example
<p>Hello <span kk-id="123">John Doe</span></p>
where John Doe's id is 123 saved in it.
/// react component
import React, { useEffect, useState } from "react";
export default function TestComponent() {
const [html, setHtml] = useState(
`<p>Hello <span kk-id="123">John Doe</span><br /></p>`
);
useEffect(() => {
const span = document.querySelector(`[kk-id]`);
if (span) {
const a = document.createElement("a");
a.href = "/people/john-doe";
a.innerText = span.innerText;
span.parentNode.replaceChild(a, span);
}
}, [html]);
return <div dangerouslySetInnerHTML={{ __html: html }} />;
}
You can use html-react-parser and just do
import parse from "html-react-parser";
...
const newParsedHtml = parse(html, {
replace: ({attribs}) => {
if (domNode.attribs && domNode.attribs.id === "123") {
return <span>dynamic text here</span>
}
}
});
I hope vanilla js is the simplest way to do it. For enhancement purpose you can see this. it will be more readable and reusable.

How to get the length of the text inside the React component

I have React component, where I have some dynamic text:
...
let spanLength
return(
<SomeComp>
...
<span>Some static text: {someDynamicText}, {someAnotherText}</span>
...
</SomeComp>
)
How can I get the length of text inside span element to a spanLength variable?
You can add a ref to your span
let spanRef = React.createRef()
...
<span ref={spanRef}>Some static text: {someDynamicText}, {someAnotherText}</span>
Then the text length would simply be spanRef.current.textContent.length
Why not, first, compose the whole string? You can grab its length immediately after, and then render it.
const spanStr = `Some static text: ${someDynamicText}, ${someAnotherText}`;
const spanLength = spanStr.length;
return(
<SomeComp>
...
<span>{spanStr}</span>
...
</SomeComp>
)

Parse nested HTML that's within a string in React?

I'm building a type ahead feature in React.
I have wrapper component that has an array of objects, and it renders item; which's a stateless component.
So, suppose I have const name= 'Hasan'. Which gets parsed to >> const parsedName = Ha<span>san</span>; assuming the term to search for is san.
I have tried dangerouslySetInnerHTML={{ __html: parsedName }} attribute on the parent element, but it didn't work.
With plain html this would be: el.innerHTML = parsedName
The goal is to style the span as desired. Any ideas?
class Test extends React.Component {
render() {
const name = 'san';
const parsedName = name.replace(new RegExp('san', 'ig'), '<span>span</span>');
return (
<div dangerouslySetInnerHTML={{__html: parsedName}}/>
);
}
}
ReactDOM.render(
<Test/>,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
</div>
Without code its hard to tell what's wrong. I have created a working snippet here that might help you debug your issue.
Updated the example based on the comment.

How to provide dynamic className to element in React Class render method

I have a ReactClass with name Alert. Its render method returns a div with class alert alert-success or alert alert-error according to the type passed while creating element. I just want to know how to add class based on the type of alert element.
Here is my attempt:
var Alert = ReactClass({
render: function() {
return <div className="alert {this.props.type}">{this.props.message}</div>
}
});
var successAlert = React.createElement(Alert, {
type: 'alert-success'
message: 'Information saved successfully!!'
});
When JSX Template is compiled this.props.type is not converted to the class passed to element. How to achieve this ?
Looks like I have found answer to my question. We can simply do something like this:
var Alert = ReactClass({
render: function() {
return <div className={"alert " + this.props.type}>{this.props.message}</div>
}
});
Just put your classes inside Template evaluators { } in this case. Create your class string based on your props and states.
Hope this is helpful to others.
One way to accomplish this is to have a string which will contain all of your classes and then set it to the Component's className:
var Alert = ReactClass({
var yourClassName = 'alert ';
// Add any additional class names
yourClassName += this.props.type + ' ';
render: function() {
return <div className={yourClassName}>{this.props.message}</div>
}
});
or alternatively you can store your class names in an array and convert it to a class friendly string when you're ready to use it:
var Alert = ReactClass({
var yourClassArray = [];
// Add any additional class names
yourClassArray.push('alert');
yourClassArray.push(this.props.type);
var classString = yourClassArray.join(' ');
render: function() {
return <div className={classString}>{this.props.message}</div>
}
});
Take a look at the classnames package. You can do stuff like this:
className={classNames('alert', `alert-${type}`)}
or
className={classNames({
'alert': true,
'alert-success': success,
'alert-error': error
})
You can use JavaScript template literals
var Alert = ReactClass({
render: function() {
return <div className={`alert ${this.props.type}`}>{this.props.message}</div>
}
});
Your code can be written in following way:
const Alert = ({type, message}) =>
<div className={`alert ${type}`}>{message}</div>
Write in code
className={`form-control-sm d-inline per_player ${"per_player_b_" + index + "_score"}`}
and You will get

Categories

Resources