HTML not rendered inside tooltip from react-tooltip - html

I used tooltip form react-tooltip and I want to inside tooltip put some HTML tags. How to manage this? I don't find any information in react-tooltip site.
For now I create Tooltip:
const TooltipConst = props => {
if (props.tooltip && props.id) {
const tooltip = <Tooltip id={props.id + 'Tooltip'}>
<div> render(){props.tooltip} </div>
</Tooltip>;
return (
<OverlayTrigger
overlay={tooltip}
placement="top"
delayShow={500}
delayHide={1000}
>
{props.children}
</OverlayTrigger>
);
}
return <div>{props.children}</div>;
};
And when pass as tooltip some string with HTML they not rendered. Any advice?
I try also put as object, for example <span><p>some text</p> Some text </span>, but it return not text but something like Object[] as tooltip.

If you want to add html in ReactTooltip, like html button or other html tags in it. And wants to show on click.
<div id={row.index} className="text-center">
<a data-tip={'dummystring'} data-event={'click focus'}
data-for={'tooltip'}>Show tooltip</a>
<ReactTooltip id={'tooltip'} effect="solid"
clickable={true} place="right"
getContent={function() {
return (
<div>
<span>Some text</span>
<Button
onClick={()=>alert('clicked')}>
Click Me </Button>
</div>
)
}}/>
</div>

const tooltip = (<Tooltip id={props.id + 'Tooltip'}>
<div> render(){props.tooltip} </div>
</Tooltip>);
this is by their officiel documentation
also if you want to render html through props you should use dangerouslySetHTML => see React's documentation

You can use react-tooltip library.
Pass a prop html={true} to <ReactTooltip /> as <ReactTooltip html={true} /> for more information refer this link

This is an old question but I had a look into the documentation and they now have a data-html prop to detect if you want render html markup, something like this:
<ToolTipData data-tip={text} data-html={text.indexOf('</') > -1}>
{children}
</ToolTipData>

It's not super obvious from the docs but even if you are wanting HTML to be rendered inside the tooltip, it still needs to be in a string (wrap your HTML in backticks). Setting the html prop on the tooltip under the hood sets dangerouslySetInnerHtml on the string you pass in.
const inner = `<p>I'm html in a string</p><p>Same</p>`
and your tooltip:
<ReactTooltip
html={true}
id={"tooltip"}
place="right"
type="dark"
effect="solid"
>
{inner}
</ReactTooltip>

Related

Why does react not compile HTML present in a state

I set a default value of a state to be <b> Hey </b> . Now when I rendered this state on the UI it printed the string instead of Hey wrote in bold.I want to know why it is not working. Why react is not able to interpret the html tag and show the appropriate output
import { useState } from "react";
import "./styles.css";
export default function App() {
const [html, setHtml] = useState("<b>Hey</b>");
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div>{html}</div>
</div>
);
}
Output :-
Was expecting the output to be Hey written in bold.
Here's the codesandbox link for better understanding :- https://codesandbox.io/s/heuristic-chaum-vo6qt?file=/src/App.js
Thank you. I just want to know why react is not able to render the HTML tag as HTML tag instead of printing it out.
Because you are rendering a string, not HTML. If you want to render stringified HTML then use dangerouslySetInnerHTML, use caution what you pass through, in other words, you may want to run the string through a DOM purifier first.
export default function App() {
const [html, setHtml] = useState("<b>Hey</b>");
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div dangerouslySetInnerHTML={{ __html: html}} />
</div>
);
}
You are setting the value of html as "<b>Hey</b>" which is a string string that's why it renders that as it is. You can directly assign html to the variable like so:
const [html, setHtml] = useState(<b>Hey</b>);
It's a string and not HTML, to fix that maybe you can insert it in the div as innerHTML ie.
document.querySelector(".divClassName").innerHTML = html

Anchor Tag in Next.js

I'm tryin got use an anchor tag in Next.js
I don't get any console errors when I set it up and click the link, but the page does not jump to the id tag.
This issue on github suggests that people need to figure out a lot of custom code to use anchors. That can't be right.
I have:
const links = [
{ label: 'Solutions', href: '#solutions', id: 'solutions' },
]
<NavLink.Desktop key={index} href={link.href} id={link.id}>
{link.label}
</NavLink.Desktop>
I get no errors, but the page does not jump to the label that has an id of 'solutions'.
Does anyone know how to solve this, or where to go for ideas on how - it can't be intented that complex custom code is required to use an anchor tag?
Chakra UI has a Link component
<Link href='https://chakra-ui.com' isExternal>
Chakra Design system <ExternalLinkIcon mx='2px' />
</Link>
If you use the regular anchor tags
<Link href="#anchor_one">Menu one</Link>
<Link href="#anchor_two">Menu two</Link>
Then you can add the id for the anchors to the sections you want to navigate into
<div id="anchor_one" />
<div id="anchor_two" />
This can be either pages or components.
I hope this helped a little bit.
As said by #juliomalves in the comments, you have to specify the id attribute on the element in which you wish to navigate to. Not on the anchor tag.
The id for the anchor should be set on the element you want to link to, not on the link itself.
The below code works for me in Next.js -
export default function Home() {
return (
<div>
Click
<section
style={{ marginTop: "1000px", marginBottom: "1000px" }}
id="section"
>
<h1>Test</h1>
</section>
</div>
);
}
Your code should look like this -
const links = [{ label: 'Solutions', href: '#solutions', id: 'solutions' }]
<NavLink.Desktop
key={index}
href={link.href}
// id={link.id} - This is wrong, as you're referring to the same element
>
{link.label}
</NavLink.Desktop>
// Rather set the id attribute in a separate div/section element
<div id={link.id}>
<h2>Solutions</h2>
</div>
maybe try
const links = [
{ label: 'Solutions', href: '#solutions', id: 'solutions' },
]
<NavLink.Desktop key={index} href={links[0].href} id={links[0].id}>
{link.label}
</NavLink.Desktop>
since you only have 1 element in the links array, if you have multiple just map through the array
It is possible to scroll to anchor programatically using Router.push:
import { useRouter } from 'next/router'
const Foo = () => {
const { push } = useRouter()
const handleClick = () => {
push("#blah")
}
return (
<div>
<button onClick={handleClick}>Scroll</button>
<div>Foo</div>
<div>Bar</div>
<div id="blah">Blah</div>
</div>
)
}
Next.js recognises that you are passing something that is not a link to a new page and will concat it (in the example #blah) to the end of the URL.
Have a read about Link from next/link its a built in feature.
https://nextjs.org/docs/api-reference/next/link
https://github.com/vercel/next.js/blob/canary/examples/hello-world/pages/index.js#L7

Trying to get an overlay to toggle on a repeating element. Can't use getElementByID

As per the title I want an overlay to trigger when an image is clicked on, but I then want it to disappear if anywhere other than 3 buttons on the overlay are clicked.
Unfortunately using getElementbyID won't work as the items repeat on a masonry layout.
<Masonry
breakpointCols={breakpointColumnsObj}
className="my-masonry-grid"
columnClassName="my-masonry-grid_column">
{this.state.data.map((data) => (
<div>
<div className="tilebutton" key="" style={{width:'100%',position:'relative'}} href={data.URL} >
<div className="tileoverlay" id="overlay" onClick={overlayoff} onclickout key={data.URL} style={{display:'none',width:'100%',zindex:'2',position:'absolute'}}>
<a className="button1" href={data.URL} onClick>{data.Name}</a>
<a className="button2" href={data.CompURL}>{data.Company}</a>
<a className="button3" href={'instagram.com/'+data.insta}>{data.Company}<img src="\img\Icons\instagram.svg" className='instalogo'/></a>
</div>
<img src={data.img} onClick={overlayon} style={{width:'100%'}}/>
</div>
</div>
))}
</Masonry>
)
function overlayon() {
document.getElementById("overlay").style.display = "block";
}
function overlayoff() {
document.getElementById("overlay").style.display = "none";
}
Unfortunately using the id "overlay" means if I click any version of the masonry it will trigger the overlay on the first image. Is there some way to:
a) identify the element clicked so it will be the one with the toggling overlay
b) have an "onclickout" I could apply to the overlay's buttons
this is about 5 days into my first ever web build so frankly I haven't got a clue what I am doing - any help is appreciated.
Thanks in advance.
The idioms used in React discourages you to manipulate the DOM directly, unless you are doing something special, such as animation. And thus I don't recommend "identifying the element clicked".
With that said, you can manipulate the data, and trigger a redraw accordingly, by invoking some setSate function (in the example below, I've defined a setShouldShowOverlay, that, when invoked, will result in a redraw).
What I recommend is for you to pull out the code inside this.state.data.map() into its own component, like so:
import React, { useState } from 'react';
function Data({ data }) {
const [ shouldShowOverlay, setShouldShowOverlay ] = useState(false);
return (
<div>
<div className="tilebutton" key="" style={{width:'100%',position:'relative'}} href={data.URL} >
<div className="tileoverlay" id="overlay" onClick={() => { setShouldShowOverlay(false); }} onclickout key={data.URL} style={{display:'none',width:'100%',zindex:'2',position:'absolute'}}>
<a className="button1" href={data.URL} onClick>{data.Name}</a>
<a className="button2" href={data.CompURL}>{data.Company}</a>
<a className="button3" href={'instagram.com/'+data.insta}>{data.Company}<img src="\img\Icons\instagram.svg" className='instalogo'/></a>
</div>
<img src={data.img} onClick={() => {
setShouldShowOverlay(true);
}} style={{width:'100%'}}/>
</div>
</div>
);
}
Then finally, update your Masonry code like so:
<Masonry
breakpointCols={breakpointColumnsObj}
className="my-masonry-grid"
columnClassName="my-masonry-grid_column">
{this.state.data.map((data) => (
<Data data={data} />
))}
</Masonry>

Reactjs: How to put HTML into primaryText of a list item?

I would like to have a span inside the ListItem like this:
<ListItem
primaryText={"<span class='inner'>Some important info</span>" + item.title}
/>
When this is rendered, I don't get an HTML span element, but a text <span class='inner'>Some important info</span>Title of the list item. How to make HTML render as HTML?
Remove "" around the span, because when you use " it will get converted into string, it will not be treated as html tag.
Write it like this this:
primaryText={<div>
<span className='inner'>Some important info</span>
{item.title}
</div>}
Note: class is reserved keyword so, to apply css classes use className.
EDIT: Ignore me, just saw you needed it specifically for a ListItem
If you need to render HTML within an element, you can use the dangerouslySetInnerHTML prop (but it comes with some risks, and the name suggests):
function createMarkup() {
return {__html: 'First ยท Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
Docs here:
https://facebook.github.io/react/docs/dom-elements.html#dangerouslysetinnerhtml
Based on the info given, you should move the span inside the ListItem component and deal with it there rather than passing in the props.
<ListItem
primaryText={ 'Some important info' }
title={ item.title }
/>
//List Item Component
import React from 'react'
const ListItem = ( props ) => {
return (
<li>
<span className='inner'>{ props.primaryText }</span>{ ` ${props.title}` }
</li>
)
}
export default ListItem

html element as react-bootstrap button title, using ES6 syntax?

I am implementing a button using React Bootstrap and ES6 syntax, but I'd like to have the title be responsive to media queries... if the window is too small, then the word 'amazing' should be hidden from the button title "Use this amazing Product". I'm fine with writing the CSS side (.optionalSubstring {display: none;}), but how can I get the title attribute of the button to receive an html element rather than a string?
The following (i.e., simply wrapping the desired title in single quotes) does NOT work, as it renders the dropdown button literally with the title "Use this <span className="optionalSubstring">amazing </span>Product"
And sorry, but it has to be a CSS solution, not a JS one.
import {default as React, Component} from 'react';
import {Button, DropdownButton, MenuItem} from 'react-bootstrap';
export default class MyDropdown extends Component {
onSelectOpen = (eventKey) => {
//do something
};
render() {
let myTitle = 'Use this <span className="optionalSubstring">amazing </span>Product';
return (
<div className="menuWrapper">
<DropdownButton bsSize="small" dropup bsStyle="default4" title={myTitle} id="ShowInProductMenu">
<MenuItem eventKey="foo1" onSelect={this.onSelectOpen}>Foo One</MenuItem>
<MenuItem eventKey="foo2" onSelect={this.onSelectOpen}>Foo Two</MenuItem>
<MenuItem eventkey="foo3" onSelect={this.onSelectOpen}>Foo Three</MenuItem>
</DropdownButton>
</div>
);
}
}
They're not doing anything fancy with {title} in the component as you can see from the source https://github.com/react-bootstrap/react-bootstrap/blob/master/src/DropdownButton.js#L25
Meaning you can pass in a jsx element instead of a string.
let myTitle =
<span>
Use this <span className="optionalSubstring">amazing </span>Product
</span>