Dynamic form only shown on refresh - reactjs

I've been having an issue where the client has provided me a third party Marketo form to include on one of the pages I'm building out which works on a "normal" html page when testing locally, however on Gatsby, it's not working. The script that was provided is as follows:
<script src="//app-xxxx.marketo.com/js/forms2/js/forms2.min.js"></script>
<form id="mktoForm_xxxx"></form>
<script>MktoForms2.loadForm("//app-xxxx.marketo.com", "xxx-xxx-xxx", xxxx);</script>
I've added the top script tag into gatsby-ssr.js like so:
import React from 'react'
export const onRenderBody = ({ setPostBodyComponents }) => {
setPostBodyComponents([
<script
key="mktoForm_test"
src="//app-sjst.marketo.com/js/forms2/js/forms2.js"
/>,
<script
key="/js/site.js"
src="/js/site.js"
/>
])
I've added the following to /static/js/site.js to initialize the form:
MktoForms2.loadForm("//app-xxx.marketo.com", "xxx-xxx-xxx", xxxx);
Then, on the page where I want the form, I've added this:
<form id="mktoForm_xxxx"></form>
The form only displays when I'm on the page and manually refresh the browser. Clicking into the page from any other page does not render the form at all. I'm guess it's how Gatsby/React routes to the page with the form.
Can someone please help??

You probably need to call that .loadForm function when the component that has that form mounts.
React.useEffect(() => {
// load form here...
}, []
If it's just being called in site.js, it's probably being called before the form element is present in the DOM so it has nothing to attach to.
I created this example a while ago, leaving it here in case it's extra help: https://github.com/CharlieDieter/react-marketo-hook

Related

Changing the route when opening a modal but not navigating to it

Instagram example
As in the image above, in the user profile page with a url(profile/:username), the user is able to click on one of his posts which opens a modal containing that specific post, the url thereafter changes to p/:postId but doesn't navigate to another page, it instead displays above the profile page without navigating to p/:postId
I'm trying to do the same in my app and I have tried doing stuff like history.push but it's not working and I assume this is happening cause of react-router.
To achieve the behavior you described, you can use React Router to manage the URL change and display the modal with the post content.
Define a route in your React Router configuration that corresponds to the modal content you want to display. For example
<Route path="/posts/:postId" component={PostModal} />
In your component, include a link to the new route with the post ID as a parameter.
<Link to={`/posts/${postId}`}>View Post</Link>
In your PostModal component, use the useParams hook to access the post ID parameter from the URL. Then, fetch the post data from your API or store, and display it.
import { useParams } from 'react-router-dom';
function PostModal() {
const { postId } = useParams();
// Fetch post data and display it in modal
}
After that, Use CSS to display the modal as an overlay on top of your existing content, and use JavaScript to show and hide the modal as appropriate.

Script not being executed while navigating, it works only if I refresh the page

I'm trying to insert a script on a gatsby project, but the script doesn't load, it loads only if I refresh the page, not while navigating.
The html.js file is same only that I inserted this line of code in the head section :
<script src={'../src/general/sendData'}/>
The script doesn't show any messages while navigating, only if I refresh the page:
window.onload = function(){
console.log('worked');
}
Try using onRouteUpdate API (from Gatsby browser, gatsby-browser.js):
exports.onRouteUpdate = () => {
console.log('worked');
}
It's a helper triggered in each route change so it should fit your specs.

angular hybrid app, lazy loaded module does not work when page refreshed

I have an angular hybrid app (angularjs with angular) with lazy loading on one of the feature modules.
The feature module is declared the following way
const contactFs: NgHybridStateDeclaration = {
name: 'contact.v2.**',
url: '/contact/v2/',
loadChildren: () =>
import(/* webpackChunkName: "contactM" */ './contacts.module').then(m => m.contactsModule)
};
I have the following states declared in the contacts module
export const state1: Ng2StateDeclaration = {
name: 'contact.v2',
url: '/'
};
export const state2: Ng2StateDeclaration = {
name: 'contact.v2.details',
url: ':id/details',
component: detailsComponent,
};
Now I can navigate to the contact.v2.details state without a problem from the home component. The url becomes something like host/contact/v2/9ee34d65-a91f-460c-9947-e2a7ee9d5538/details
The problem is that when the user clicks the refresh on the browser, it does not load the component, it just loads an empty state. Not sure what is going wrong here, it seems like it is not loading the lazy loaded module at all when hitting the refresh button.
Change in your index.html as below.
<base href='./'>
the problem is when you refresh you don't have the data (in your first call you pass the data to the detail components but when you refresh the data are not in it)
you need to use rxjs and do the call on the onInit method (i say this because i am writing same project as you using drupal 8.9)

How to add google recaptcha in create react app?

I'm trying to get the recaptcha response so that I can pass along it via redux-form.
Have tried the 2 methods below...
Attempt 1:
Specifying callback in <head>.
index.html:
<script src='https://www.google.com/recaptcha/api.js?onload=callback&render=explicit'></script>
The problem here is that the callback is in global scope but I need to access it in React components.
Attempt 2:
Specifying callback in DOM.
Component: handleRecaptcha(resp)
handleRecaptcha(resp) {
console.log(resp);
}
Component: render():
<div className="g-recaptcha" data-callback={this.handleRecaptcha.bind(this)} data-sitekey="***"></div>
index.html:
<script src='https://www.google.com/recaptcha/api.js'></script>
I get the message ReCAPTCHA couldn't find user-provided function: function () { [native code] } after submitting the recaptcha. Probably a scope problem too.
I'm trying to avoid using another library, since I think this is a rather trivial problem.
Would anyone happen to have any idea how to go about it?
All I need is to get hold of the widget instance, and do grecaptcha.getResponse(widget) to get the response. API ref
Use react-recaptcha
import Recaptcha from 'react-recaptcha'
<Recaptcha
sitekey="xxxxxxxxxxxxxxxxxxxx"
render="explicit"
verifyCallback={verifyCallback}
onloadCallback={callback}
/>
You could also try Reaptcha.
It is a lot cleaner, more modern and has more of a React-way approach in handling the reCAPTCHA widget.
<Reaptcha
sitekey="YOUR_API_KEY"
onVerify={() => {
// Do something
}}
/>

HTML markup does not change when the UI changes in isomorphic react web app

I am using react for creating a sample page which has server side rendering using renderToString() for SEO friendly pages.
this is my server.js code
app.get('*', (req, res) => {
match(
{ routes, location: req.url },
(err, redirectLocation, renderProps) => {
// in case of error display the error message
if (err) {
return res.status(500).send(err.message);
}
// generate the React markup for the current route
let markup;
if (renderProps) {
markup = renderToString(<RouterContext{...renderProps}/>);
} else {
res.status(404);
}
// render the index template with the embedded React markup
return res.render('index', { markup });
}
);
});
My page is search page which is static initially and when the user enters the input it fetches data from backend and renders a list of components in the same page.
When I see view page source in browser, I can see only the initial static content, not the html of list which renders after the backend response.
What is the right method to get the updated HTML when the component state changes.
You still need to include your component, and React itself, on your clientside and call React.render on the same base element in the DOM.
Simply serving the result of React.renderToString as static HTML does will only do exactly that, serve static html.
If you want your component to get mounted properly on the clientside so it can react to clientside events and re-render for state changes, you'll need to mount it on the static html, this is done by calling React.render on page load on the clientside.
There's more about this here: https://strongloop.com/strongblog/node-js-react-isomorphic-javascript-why-it-matters/
Save the fetched data to your state and the component will re-render itself. That way your view will render the new content when it's fetched from the backend.

Resources