Can't embed Facebook post into Next JS generated page - reactjs

I am trying to embed a public FB post into the main page of my application. I am following FB guide and it's pretty simple. It works when I do it in .html file, but doesn't with Next JS.
Basically, instructions are that you need to insert this right after the body opening tag
<div id="fb-root"></div>
<script async defer crossorigin="anonymous"
src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&autoLogAppEvents=1&version=v9.0&appId={appId}" nonce={someNonce}"></script>
and then you put the other part wherever you want.
I even created a custom _document.js file and included this script, I can also see it in the browser. But the post does not get loaded.
Anyone had this kind of issue?

Assuming you already have the JS SDK loaded in your document, like you mentioned (you might also load the script on-demand via JavaScript if preferred).
// pages/_document
class MyDocument extends Document {
render() {
return (
<Html lang="en">
<!-- additional code -->
<body>
<!-- additional code -->
<script
async
defer
src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v3.2"
/>
</body>
</Html>
);
}
}
You can then render a Facebook post inside one of your components with:
<div
className="fb-post"
data-href="https://www.facebook.com/20531316728/posts/10154009990506729/"
/>
For further details refer to the official Embedded Posts documentation.

Related

How does getStaticProps() render fetched data in the initial HTML file?

According to the Next.js official site, pre-rendered pages first display the pre-rendered HTML and then hydrate it by initializing the React components and making it interactive (adding the event listeners). If this is the case, how is it that the props passed to the component via getStaticProps() (see generic example below) manipulate the initial HTML render? Isn't the React code just running server-side to inject the desired data into the pre-rendered HTML, then running again later to hydrate it?
export async function getStaticProps() {
// Get external data from the file system, API, DB, etc.
const data = ...
// The value of the `props` key will be
// passed to the `Home` component
return {
props: ...
}
}
getStaticProps() works even when there is no "server-side", i.e. when you've next exported your site to just static files. Hence it's not "React code just running server-side".
If you look at a next exported page, you'll see it's something like
<!DOCTYPE html>
<html lang="en">
<head>
...
<script src="/_next/client-side-script-stuff-here.js"></script>
</head>
<body>
<div id="__next" data-reactroot="">
<h1>Bare rendered HTML here, no scripts...</h1>
</div>
<script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"somePageProp":...}}, "__N_SSG":true},"page":"/","query":{},"buildId":"..."}</script>
</body>
</html>
and it's the client-side-script-stuff-here.js in conjunction with the injected __NEXT_DATA__ that has React and Next's machinery hydrate the page.

How can I inject arbitrary string HTML content into the head of my gatsbyjs site?

I have a GatsbyJS site that I am working on where the main content source is a Wordpress install. One of the things I like to add to my sites is the ability to have placeholder areas in the site where I can control the content via the CMS. Usually I have a header_scripts area that goes at the bottom of the <head> tag, a body_scripts area that goes at the start of the <body> tag, and a footer_scripts area that goes at the bottom of the page <body>. With these three, I can usually integrate third-party add-ins pretty easily without having to do code deployments.
Sometimes I need to embed stylesheets, sometimes I need to embed script tags, and sometimes I need to throw in <meta> tags. Really the content could be anything. This data comes back as a raw string from my Wordpress GraphQL endpoint.
So now my question is, how do I get this content injected into my Gatsby site in the following places:
<html>
<head>
...
{header_scripts}
</head>
<body>
{body_scripts}
...
{footer_scripts}
</body>
</html>
I've found so far that I can just include the body_scripts and footer_scripts in a fairly regular manner in my Gatsby page template. In gatsby-node.js, I pass in the property values using the pageContext. It's kind of a bummer that they need to be wrapped in a <div /> tag, but they seem to work just fine.
import React from 'react'
export default class PageTemplate extends React.Component {
render = () => {
return (
<React.Fragment>
{this.props.pageContext.bodyScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.bodyScripts}} />
)}
{/* my page content here */}
{this.props.pageContext.footerScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.footerScripts}} />
)}
</React.Fragment>
)
}
}
Now for the real question. I am stumped on how to get the dynamic content from the header_scripts into the Gatsby server-side-rendering <head> tag. The closest thing I have found to being able to inject content into the head is to leverage the gatsby-ssr.js onRenderBody function. However, this seems to require pre-determined React component instances in order to function. I can't just pass it in plain raw string content and see the output in the page source:
export const onRenderBody = async ({
pathname,
setHeadComponents,
setHtmlAttributes,
setBodyAttributes,
setPreBodyComponents,
setPostBodyComponents,
setBodyProps
}, pluginOptions) => {
setHeadComponents(['<script>alert("hello");</script>'])
}
This results in an escaped string getting inserted into the <head> tag:
<html>
<head>
...
<script>alert("hello");</script>
</head>
<body>
...
</body>
</html>
I'm at a loss as to how to proceed. I can't just wrap my string in a <div /> tag like in the body because div tags can't go inside the head tag. I can't think of any head-capable HTML tags that would accept this kind of content.
The only idea I've had is to actually parse the string content into full React components. This seems daunting given the number of possible tags & formatting that I would need to support.
Am I going about this the wrong way? How can I get my arbitrary content into my Gatsby site's head tag?
It's a broad question and it will need some trials and errors to ensure that it's fully working without caveats in all scenarios but, among the things you've tried, you can add a few more options to the list to check which ones fit better.
Regarding the body_scripts and footer_scripts both can be inserted using the:
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.footerScripts}} />
In any desired page or template. For the header_scripts and the meta tags (SEO), you can use the <Helmet> component. Basically, using this component, everything that is wrapped inside, it's becomes transpiled inside the <head> tag once compiled.
export default class PageTemplate extends React.Component {
render = () => {
return (
<React.Fragment>
<Helmet>
{this.props.pageContext.headerScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.headScripts}} />
)}
</Helmet>
{this.props.pageContext.bodyScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.bodyScripts}} />
)}
{/* my page content here */}
{this.props.pageContext.footerScripts && (
<div dangerouslySetInnerHTML={{__html:this.props.pageContext.footerScripts}} />
)}
</React.Fragment>
)
}
}
However, if the data comes from a CMS, it won't be available in the SSR yet, so, one easy thing you can do is to customize the outputted HTML (html.js) that Gatsby generates in each compilation. From the docs:
Customizing html.js is a workaround solution for when the use of the
appropriate APIs is not available in gatsby-ssr.js. Consider using
onRenderBody or onPreRenderHTML instead of the method above. As a
further consideration, customizing html.js is not supported within a
Gatsby Theme. Use the API methods mentioned instead.
Run:
cp .cache/default-html.js src/html.js
Or manually, copy the .cache/default-html.js file and paste it /src folder. There you can customize the final HTML.

How to use visualforce page with lightning:container React in Lightning app builder?

I try to create a React app inside visualforce page via lightning. When I click preview in visualforce setting, everything is fine.
But when I use it in Lightning app builder it does not work. It shows
The error: Refused to frame 'https://mirage-video-dev-ed--ltng.container.lightning.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors https://mirage-video-dev-ed--c.visualforce.com".
Also really weird that if I right click and choose "Reload frame", it works.
Visualforce code
<apex:page >
<apex:includeLightning />
<div id="hello" />
<script>
$Lightning.use("c:myFirstApp", function() {
$Lightning.createComponent("lightning:container",
{ src: "{!$Resource.hello + '/index.html'}"},
"hello",
function(cmp) {
console.log("created");
// do some stuff
}
);
});
</script>
</apex:page>
myFirstApp
<aura:application access="global" extends="ltng:outApp">
<aura:dependency resource="lightning:container"/>
</aura:application>
Is there a way to fix it? I cannot find the way to load aura:application directly so if there is a way please show me.
You've got a bit of a inception problem going on... You just need to mount your react app directly inside of the VF page. No need to use a lightning:container.
See my B.A.S.S. project. This is proven to work and be extremely scalable.
Example VF Page with react app:
<apex:page showHeader="true" sidebar="false" standardStylesheets="false" docType="html-5.0">
<script type="text/javascript">
//rest details
const __ACCESSTOKEN__ = '{!$Api.Session_ID}';
const __RESTHOST__ = '';
</script>
<div id="root"></div>
<!-- Your react entry point -->
<script type='text/javascript' src="{!URLFOR($Resource.app, 'dist/app.js')}"></script>
</apex:page>
It is also possible to to run a React App directly inside a LWC, although no recommended.

Send PDF as attachment using React and .Net Core Web Api

I found alot of outdated options on the web so Just wandering what should be the best approach to convert DOM, as an PDF attachment and then send it via email.
I am using React as Front-end and .Net Core web Api as backend.
Thanks in Advance :)
Download jsPDF from Github Include these scripts below:
jspdf.js
jspdf.plugin.from_html.js
jspdf.plugin.split_text_to_size.js
jspdf.plugin.standard_fonts_metrics.js
If you want to ignore certain elements, you have to mark them with an
ID, which you can then ignore in a special element handler of jsPDF.
Therefore your HTML should look like this:
<!DOCTYPE html>
<html>
<body>
<p id="ignorePDF">don't print this to pdf</p>
<div>
<p><font size="3" color="red">print this to pdf</font></p>
</div>
</body>
</html>
Then you use the following JavaScript code to open the created PDF in
a PopUp:
var doc = new jsPDF();
var elementHandler = {
'#ignorePDF': function (element, renderer) {
return true;
}
};
var source = window.document.getElementsByTagName("body")[0];
doc.fromHTML(
source,
15,
15,
{
'width': 180,'elementHandlers': elementHandler
});
doc.output("dataurlnewwindow");
One very important thing to add is that you lose all your style
information (CSS). Luckily jsPDF is able to nicely format h1, h2, h3
etc., which was enough for my purposes. Additionally it will only
print text within text nodes, which means that it will not print the
values of textareas and the like. Example:
<body>
<ul>
<!-- This is printed as the element contains a textnode -->
<li>Print me!</li>
</ul>
<div>
<!-- This is not printed because jsPDF doesn't deal with the value attribute -->
<input type="textarea" value="Please print me, too!">
</div>
</body>
Attach the pdf and send emails with the help of this link

ReCaptcha & Underscore.js Templates

I am running into an issue in my backbone/underscore application. Our site uses recaptcha and we want to put that content inside a view. We are using underscore for templates. How would i put the recaptcha code inside a template? THe problem is there are scripts tags required for recaptcha and it collides with the underscore script tag. For example it would look something like this:
<script type="text/javascript" id="someTemplate">
<div>
some html here
</div>
<script type="text/javascript" src="https://www.google.com/recaptcha/api/challengek=YOUR_PUBLIC_KEY"
 
</script>
any help is appreciated. Thanks!
Underscore does not prevent you from using script tags, your problems come from your template declaration : you use type="text/javascript" which means your browser tries to interpret your template as Javascript and you get erratic results.
Try
<script type="text/template" id="someTemplate">
<div><%= text %></div>
<script type="text/javascript"
src="https://www.google.com/recaptcha/api/challengek=<%= key %>"
/>
</script>
and a demo http://jsfiddle.net/VxjBs/
As you noted in the comments, Recaptcha tries to loads a second script via document.write and fails when inserted in the DOM (see Can't append <script> element for a probable explanation).
Your best bet is probably to go through Recaptcha Ajax API, generate your HTML, identify a node and apply Recaptcha.create on it. Something like
<script type="text/template" id="someTemplate">
<div><%= text %></div>
<div class='recaptcha'></div>
</script>
The basis for a view could be
var html = _.template(src, {
text: 'in div'
});
var $el = $('#render').append(html);
$el.find('.recaptcha').each(function(idx, el) {
Recaptcha.create(
pubkey,
el
);
});
http://jsfiddle.net/nikoshr/VxjBs/2/
Not sure what all the reCAPTCHA script does, but I'm assume it tries to append HTML right after itself. If that's the case then you will probably need to manually attach a script node to the view after you've rendered it and then set the src of the script node to the URL of the external javascript file.
You cannot put script tags inside an underscore template as the browser will only parse the outer-most script tag (your template).
The proposed solution is too complicated.
This can be achieved very easily as follows (in fact I've just implemented it in my project).
Make sure to include the recaptcha js file in the "head" element of your page as follows:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
Add this function in your javascript somewhere.
var render_recaptcha = function(target_id) {
grecaptcha.render(target_id, {
'sitekey' : RECAPTCHA_SITE_KEY
});
};
Then, just call this function after you render your template:
<script type="text/template" id="someTemplate">
<div><%= text %></div>
<div id='recaptcha'></div>
</script>
//render template like you usually would
//...
//then render the recaptcha
render_recaptcha('recaptcha');
That's it.

Resources