Why isn't Disqus Universal Code working? - javascript

I want to use it for my website, but having trouble loading it. Nothing shows up.
I tried clearing my caches and cookies, and disabling all plugins, extensions, and add-ons, but it still does not work.
Here is the following code:
import React, { Component } from 'react'
import { Divider } from 'material-ui'
const styles = {
title:{
color: 'white',
textAlign: 'left',
marginLeft: 30
}
}
export default class TestingDisqus extends Component{
render(){
return(
<div>
<div style={styles.title}>
<font size="4">
Testing Disqus
</font>
</div>
<Divider style={{backgroundColor:'#282828'}}/>
<div id="disqus_thread"></div>
<script>
(function()
var d = document, s = d.createElement('script');
s.src = '//testingdisqus.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the comments powered by Disqus.</noscript>
</div>
)
}
}
Any insights would be appreciated! Thank you in advance.

In React it's best not to select and directly manipulate the DOM. React uses a virtual DOM and does the DOM manipulation for you. Also you have an IIFE in your JSX and in JSX you need to wrap all of your javascript in curly braces.
I recommend finding a React solution for this instead of trying to use vanilla JS in your JSX. Here is an open source react component that will likely solve your problem or get you started.
React-disqus-thread
import React from 'react'
import ReactDisqusThread from 'react-disqus-thread'
// in your class you can add this:
handleNewComment: function(comment) {
console.log(comment.text);
}
render: function () {
// and put a ReactDisqusThread in your JSX
return (
<ReactDisqusThread
shortname="example"
identifier="something-unique-12345"
title="Example Thread"
url="http://www.example.com/example-thread"
category_id="123456"
onNewComment={this.handleNewComment}/>
);
}
});

Related

How to load an external script and access it from the main bundle in nextJS

I am working with mercadopago library. It's necessary to load the mercadopago script file and make an instance of the MercadoPago object. The thing is, nextJS loads the main bundle before including the mercadopago file, so I got an execution error because the object is not defined.
I tried different ways, loading the script file into the Head component with a normal tag and with the Next/Script object like:
<script src="https://sdk.mercadopago.com/js/v2" strategy="beforeInteractive"/>
Does not matter what I do, next always loads the script after the main bundle file. If I set a setTimeout to wait to instance the Mercadopago object it runs, but obviously this is not a good option. Which is the correct way to solve this?
Load the script in _document.js before next.js scripts, create _document.js in pages directory to extend the html document the way you like.
import Document, { Html, Head, Main, NextScript } from "next/document";
export default class MyDocument extends Document {
render(){
return (
<Html>
<Head>
/*This is loads the script in head tag of your html document*/
<script src="https://sdk.mercadopago.com/js/v2" strategy="beforeInteractive"/>
</Head>
<body>
/*your script can also go here before loading next scripts*/
<Main />
<NextScript />
</body>
</Html>
)
}
}
OK, I solved this using the onLoad method available on Next/Script component. What I needed to do was to move the script inclusion to my own component and include the component there adding the onLoad props and passing a function that executed my object instance after loading it.
Here my code:
const onload = () => {
const controller = new Controller(props);
setController(controller);
};
const pay = () => controller.load(props.disabled);
const attrs = {onClick: pay};
if (!controller || props.disabled) attrs.disabled = true;
return(
<>
<section className="mercadopago-checkout-pro-component">
<div ref={refContainer} className="cho-container">
<button className="btn btn-secondary" {...attrs}>
Pay
</button>
</div>
</section>
<Script src="https://sdk.mercadopago.com/js/v2" onLoad={onload}/>
</>
);
Go to your component where you need this script.
import Script from 'next/script'
const myComponent = () => {
const [razorpayInstance, setRazorpayInstance] = useState();
const handleLoadScript= () => {
var options: any = {
"key": "myKey"
};
res = new Razorpay(options);
setRazorpayInstance(razorpay)
}
return( <> <Script id="onload-id" src="https://mycdn.com/slugs" onLoad={handleLoadScript} /> </> )};
export default myComponent;

Render Reddit embed into ReactJs Component

I am unable to render properly the reddit embed for a post, for some reason, when the iframe generates, the height gets cut off. If I manually select the iframe from developer tools, and uncheck "height: auto" it resizes properly. I have no idea how to fix this or what might be causing this issue. Any help would be appreciated. Thank you.
import React from 'react';
export default class RedditEmbedComponent extends React.Component {
componentWillMount() {
const script = document.createElement("script");
script.src = "//embed.redditmedia.com/widgets/platform.js";
script.async = true;
document.body.appendChild(script);
}
renderFrame = () => {
return (
<div>
<blockquote class="reddit-card" data-card-created="1553892582">
<a href="https://www.reddit.com/r/science/comments/b6wjlb/a_billion_people_may_be_newly_exposed_to_diseases/">
A billion people may be newly exposed to diseases like dengue fever as world temperature rises by the end of the century because of global
warming, says a new study that examines temperature changes on a monthly basis across the world.</a> from
r/science</blockquote>
</div>
);
}
render() {
return (<div>
{this.renderFrame()}
</div>);
}
}

React/webpack conditionally return require.ensure component (code splitting)

I have a sub component that does not need to be loaded immediately that I want to split out. I am trying to conditionally load in a react component via require.ensure. I am not getting any console errors but I am also not seeing anything being loaded. Here is the code I am calling :
renderContentzones() {
if (this.props.display ) {
return require.ensure([], () => {
const Component = require('./content-zones/component.jsx').default;
return (
<Component
content={this.props.display}
/>
);
});
}
return null;
}
It is just rendering a blank screen currently (no errors). This previously worked when I used import 'displayComponent' from './content-zones/component.jsx' and just returned it like you normally would in react, instead of this require.ensure but. Not sure what I am doing wrong here, any idea how to make something like this work? Thanks!
This is one way to do it, using the state to show the dynamic loaded component:
constructor(){
this.state = {cmp:null};
}
addComponent() {
const ctx = this;
require.ensure(['../ZonesComponent'], function (require) {
const ZonesComponent = require('../ZonesComponent').default;
ctx.setState({cmp:<ZonesComponent />});
});
}
render(){
return (
<div>
<div>Some info</div>
<div><button onClick={this.addComponent.bind(this)}>Add</button></div>
<div>
{this.state.cmp}
</div>
</div>
);
}
When you press the button add the component will be shown.
Hope this help.

How to combine JSX component with dangerouslySetInnerHTML

I'm displaying text that was stored in the database. The data is coming from firebase as a string (with newline breaks included). To make it display as HTML, I originally did the following:
<p className="term-definition"
dangerouslySetInnerHTML={{__html: (definition.definition) ? definition.definition.replace(/(?:\r\n|\r|\n)/g, '<br />') : ''}}></p>
This worked great. However there's one additional feature. Users can type [word] and that word will become linked. In order to accomplish this, I created the following function:
parseDefinitionText(text){
text = text.replace(/(?:\r\n|\r|\n)/g, '<br />');
text = text.replace(/\[([A-Za-z0-9'\-\s]+)\]/, function(match, word){
// Convert it to a permalink
return (<Link to={'/terms/' + this.permalink(word) + '/1'}>{word}</Link>);
}.bind(this));
return text;
},
I left out the this.permalink method as it's not relevant. As you can see, I'm attempting to return a <Link> component that was imported from react-router.However since it's raw HTML, dangerouslySetInnerHTML no longer works properly.
So I'm kind of stuck at this point. What can I do to both format the inner text and also create a link?
You could split the text into an array of Links + strings like so:
import {Link} from 'react-router';
const paragraphWithLinks = ({markdown}) => {
const linkRegex = /\[([\w\s-']+)\]/g;
const children = _.chain(
markdown.split(linkRegex) // get the text between links
).zip(
markdown.match(linkRegex).map( // get the links
word => <Link to={`/terms/${permalink(word)}/1`}>{word}</Link> // and convert them
)
).flatten().thru( // merge them
v => v.slice(0, -1) // remove the last element (undefined b/c arrays are different sizes)
).value();
return <p className='term-definition'>{children}</p>;
};
The best thing about this approach is removing the need to use dangerouslySetInnerHTML. Using it is generally an extremely bad idea as you're potentially creating an XSS vulnerability. That may enable hackers to, for example, steal login credentials from your users.
In most cases you do not need to use dangerouslySetHTML. The obvious exception is for integration w/ a 3rd party library, which should still be considered carefully.
I ran into a similar situation, however the accepted solution wasn't a viable option for me.
I got this working with react-dom in a fairly crude way. I set the component up to listen for click events and if the click had the class of react-router-link. When this happened, if the item has a data-url property set it uses browserHistory.push. I'm currently using an isomorphic app, and these click events don't make sense for the server generation, so I only set these events conditionally.
Here's the code I used:
import React from 'react';
import _ from 'lodash';
import { browserHistory } from 'react-router'
export default class PostBody extends React.Component {
componentDidMount() {
if(! global.__SERVER__) {
this.listener = this.handleClick.bind(this);
window.addEventListener('click', this.listener);
}
}
componentDidUnmount() {
if(! global.__SERVER__) {
window.removeEventListener("scroll", this.listener);
}
}
handleClick(e) {
if(_.includes(e.target.classList, "react-router-link")) {
window.removeEventListener("click", this.listener);
browserHistory.push(e.target.getAttribute("data-url"));
}
}
render() {
function createMarkup(html) { return {__html: html}; };
return (
<div className="col-xs-10 col-xs-offset-1 col-md-6 col-md-offset-3 col-lg-8 col-lg-offset-2 post-body">
<div dangerouslySetInnerHTML={createMarkup(this.props.postBody)} />
</div>
);
}
}
Hope this helps out!

Insert HTML with React Variable Statements (JSX) [duplicate]

This question already has answers here:
ReactJS convert HTML string to JSX
(12 answers)
Closed 2 years ago.
I am building something with React where I need to insert HTML with React Variables in JSX. Is there a way to have a variable like so:
var thisIsMyCopy = '<p>copy copy copy <strong>strong copy</strong></p>';
and to insert it into react like so, and have it work?
render: function() {
return (
<div className="content">{thisIsMyCopy}</div>
);
}
and have it insert the HTML as expected? I haven't seen or heard anything about a react function that could do this inline, or a method of parsing things that would allow this to work.
You can use dangerouslySetInnerHTML, e.g.
render: function() {
return (
<div className="content" dangerouslySetInnerHTML={{__html: thisIsMyCopy}}></div>
);
}
Note that dangerouslySetInnerHTML can be dangerous if you do not know what is in the HTML string you are injecting. This is because malicious client side code can be injected via script tags.
It is probably a good idea to sanitize the HTML string via a utility such as DOMPurify if you are not 100% sure the HTML you are rendering is XSS (cross-site scripting) safe.
Example:
import DOMPurify from 'dompurify'
const thisIsMyCopy = '<p>copy copy copy <strong>strong copy</strong></p>';
render: function() {
return (
<div className="content" dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(thisIsMyCopy)}}></div>
);
}
dangerouslySetInnerHTML has many disadvantage because it set inside the tag.
I suggest you to use some react wrapper like i found one here on npm for this purpose.
html-react-parser does the same job.
import Parser from 'html-react-parser';
var thisIsMyCopy = '<p>copy copy copy <strong>strong copy</strong></p>';
render: function() {
return (
<div className="content">{Parser(thisIsMyCopy)}</div>
);
}
Very Simple :)
UPDATE
in the latest version as usage explained:
// ES Modules
import parse from 'html-react-parser';
// CommonJS
const parse = require('html-react-parser');
....
//Parse single element
parse('<li>Item 1</li><li>Item 2</li>');
//Parse multiple elements
parse('<li>Item 1</li><li>Item 2</li>');
By using '' you are making it to a string. Use without inverted commas it will work fine.
const App = () => {
const span = <span> whatever your string </span>
const dynamicString = "Hehe";
const dynamicStringSpan = <span> {`${dynamicString}`} </span>
return (
<div>
{span}
{dynamicStringSpan}
</div>
);
};
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>
import { Fragment } from 'react' // react version > 16.0
var thisIsMyCopy = (
<Fragment>
<p>copy copy copy
<strong>strong copy</strong>
</p>
</Fragment>
)
By using '' the sets the value to a string and React has no way of knowing that it is a HTML element. You can do the following to let React know it is a HTML element -
Remove the '' and it would work
Use <Fragment> to return a HTML element.
To avoid linter errors, I use it like this:
render() {
const props = {
dangerouslySetInnerHTML: { __html: '<br/>' },
};
return (
<div {...props}></div>
);
}
You don't need any special library or "dangerous" attribute. You can just use React Refs to manipulate the DOM:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.divRef = React.createRef();
this.myHTML = "<p>Hello World!</p>"
}
componentDidMount() {
this.divRef.current.innerHTML = this.myHTML;
}
render() {
return (
<div ref={this.divRef}></div>
);
}
}
A working sample can be found here:
https://codepen.io/bemipefe/pen/mdEjaMK
Try Fragment, if you don't want any of above.
In your case, we can write
import React, {useState, Fragment} from 'react'
const thisIsMyCopy = Fragment('<p>copy copy copy <strong>strong copy</strong></p>')
render: function() {
return (
<div className="content">{thisIsMyCopy}</div>
);
}
If you using hook want to set it in a state somewhere with any condition
const [thisIsMyCopy, setThisIsMyCopy] = useState(<Fragment><p>copy copy copy <strong>strong copy</strong></p></Fragment>);
If anyone else still lands here. With ES6 you can create your html variable like so:
render(){
var thisIsMyCopy = (
<p>copy copy copy <strong>strong copy</strong></p>
);
return(
<div>
{thisIsMyCopy}
</div>
)
}
You can also include this HTML in ReactDOM like this:
var thisIsMyCopy = (<p>copy copy copy <strong>strong copy</strong></p>);
ReactDOM.render(<div className="content">{thisIsMyCopy}</div>, document.getElementById('app'));
Here are two links link and link2 from React documentation which could be helpful.

Categories