ReactJS fetched html data manupilation - javascript

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.

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');

Alternative to document in next.js

I'm still new to learning next.js, but the problem is, I don't understand. How do we call an element from the written html because I want to do like the code written below?
HTML
<div class="container_title">
<div class="main_title">
<h1> Title <span>( Global )</span></h1>
<div class="button_main_title">
<button class="Tap_1 button" >Tap_1 </button>
<button class="Tap_2 button">Tap_2</button>
<button class="Tap_3 button">Tap_3</button>
<button class="Tap_4 button">Tap_4</button>
<button class="Tap_5 button">Tap_5</button>
</div>
</div>
</div>
javascript
const main_title = document.querySelector(".main_title");
const button_main_title = document.querySelectorAll(".main_title button");
(() => {
main_title.addEventListener('click', event => {
if(event.target.classList.contains("button")){
for(i=0;i<button_main_title.length;i++) button_main_title[i].classList.remove("active");
event.target.classList.add("active")
}
})
})();
const Firsr_BTN = document.querySelector(".button_main_title .button:first-child");
Firsr_BTN.click();
NextJS is a framework which is based on React, which is based on Javascript. However, the only way that I know to select an element is to use a React hook called useRef. Let me give you an example.
import React, { useRef } from 'react'
const YourComponent = () => {
const myHeading = useRef()
console.log('heading', myHeading)
return (
<div>
<h1 ref={myHeading}>Heading</h1>
</div>
)
}
Now you have your h1 as myHeading and you can modify it the way you want. Always check your console for what's the element object looks like and how to edit it.

How do I insert icon in from createElement

I am currently using Material-UI-icon and need to create the icon by in javascript.
Is there a way where I can do this?
import ThumbUpIcon from '#material-ui/icons/ThumbUp';
var thumbsup = document.createElement(ThumbUpIcon);
Thanks!
Instead of document.createElement I would use as a variable or like <ThumbUpIcon />.
You can try the following:
import ThumbUpIcon from '#material-ui/icons/ThumbUp';
var thumbsup = <ThumbUpIcon />;
Then in the return part:
const YourComponent = () => {
return (
<div>
<h1> First option: </h1>
{thumbsup}
<h1> Second option: </h1>
<ThumbUpIcon />
</div>
)
}
Additionally I would suggest to read: Creating React Elements
I hope that helps!

React - how to render HTML contained into a variable?

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.

React dangerouslySetInnerHTML Inside Fragment

I have a use-case where I need to format some text in React and also render HTML.
Here is an example of what I'm currently trying to achieve:
import React, {Fragment} from "react";
import {renderToString} from "react-dom/server";
function FormatText(props) {
const lines = props.children.split('\n');
return lines.map((line, index) => (
<Fragment key={index}>
{line}{index !== lines.length - 1 && <br/>}
</Fragment>
));
}
const content = {
first: 'This is some text\nwith new\n\nline characters - 1',
second: 'This is some text\nwith new\n\nline <strong>characters - <sup>2</sup></strong>',
};
function App() {
return (
<ol>
<li>
<FormatText>{content.first}</FormatText>
</li>
<li dangerouslySetInnerHTML={{
__html: renderToString(<FormatText>{content.second}</FormatText>)
}}/>
</ol>
)
}
As you can see, I have some content which contains \n characters and HTML. Calling the renderToString function converts the HTML into encoded characters, which means the HTML is not rendered properly.
Is there a way to render HTML inside a react fragment.
Ideally I wanted to do the following (but it doesn't):
function FormatText(props) {
const lines = props.children.split('\n');
return lines.map((line, index) => (
<Fragment key={index} dangerouslySetInnerHTML={{__html: renderToString(
<Fragment>
{line}{index !== lines.length - 1 && <br/>}
</Fragment>
)}}>
</Fragment>
));
}
<Fragment> doesn't adds any node to DOM and so you can't do dangerouslySetInnerHTML on it. It is basically a functionality provided by React to avoid addition of extra node to DOM when you needed to return more than one from return in render. So, if something doesn't exists on real DOM, you can't do anything on it.
renderToString is generally used on node server. When doing server side rendering, you want to send the html from server to client. So, better avoid renderToString also.
The issue is that, html doesn't recognises \n for new line etc. It needs html tags. The approach to use FormatText is fine or you can simply convert the \n to br and then use dangerouslySetInnerHTML inside the <li> tag.
const content = {
first: 'This is some text\nwith new\n\nline characters - 1',
second: 'This is some text\nwith new\n\nline <strong>characters - <sup>2</sup></strong>',
};
function App() {
return (
<ol>
<li dangerouslySetInnerHTML={{
__html: content.first.replace(/\n/g, "<br/>")
}}/>
<li dangerouslySetInnerHTML={{
__html: content.second.replace(/\n/g, "<br/>")
}}/>
</ol>
)
}
ReactDOM.render(<App/>, document.getElementById("root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Hope it helps. Revert for any doubts.
Hi I guess it is not possible, only way hot to pass formated html into DOm is via dom element DIV.
Maybe this link could help you or point to
https://reactjs.org/docs/dom-elements.html

Categories

Resources