i'm roking in a ASP.NET CORE MVC project and i have a React class that is a component used in a razor page.
I tried in every single way that i found in the web but seems like console.log don't show anything.
The component is render on the page and shows the properties correctly:
and this is the inspector:
class App extends React.Component{
componentDidMount() {
console.log('hi')
}
render() {
console.log(this.props)
const { Property1, Property2 } = this.props
const handler = (event) => {
console.log(event);
}
return (
<div>
<button onClick={handler}> clicca </button>
{console.log(this.props)}
<p>Property1: {Property1}</p>
<p>Property2: {Property2}</p>
<div className="box">Sono un box</div>
</div>
);
}
}
Non of them works and i don't understand why
Index.cshtml (just a simple page with the component)
#Html.React("App",new { Property1 = "value1", Property2 = "value2" })
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
Program.cs:
//configure the services for application
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddMvc().AddRazorRuntimeCompilation();
//builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddReact();
builder.Services.AddHttpContextAccessor();
builder.Services.AddJsEngineSwitcher(option => option.DefaultEngineName = V8JsEngine.EngineName).AddV8();
var app = builder.Build();
// configure middleware
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseReact(config => {
config.AddScript("~/js/App.jsx");
});
ReactSiteConfiguration.Configuration.JsonSerializerSettings.ContractResolver = new DefaultContractResolver();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
}
[EDIT]
with ReactInitJavascript at the end of the Index.cshtml when i start the page, data are showen like the component was loaded correcty, but in the inspectore says that component App is not defined.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title> - SportData</title>
<link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="/css/site.css?v=_5WottCwlLwmnX08KuvZv3ryqfP5c42il12e6LRxHqg" />
<link rel="stylesheet" href="/css/card.css?v=ZXutknPLolnM8AJ6Dofwp6kVw_54LAeyyWSi8YLbEeY" />
</head>
<body>
<div class="container">
<main role="main" class="pb-3">
<div id="react_0HMO2J0AM8AAV"><div data-reactroot=""><button> clicca </button><p>Property1: <!-- -->value1</p><p>Property2: <!-- -->value2</p><div class="box">Sono un box</div></div></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
<script>ReactDOM.hydrate(React.createElement(App, {"Property1":"value1","Property2":"value2"}), document.getElementById("react_0HMO2J0AM8AAV"));
</script> --> this is the error line
</main>
</div>
<script src="/lib/jquery/dist/jquery.min.js"></script>
<script src="/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<!-- Visual Studio Browser Link -->
<script type="text/javascript" src="/_vs/browserLink" async="async" id="__browserLink_initializationData" data-requestId="6501a3e3c110465981ca8b97a81c1842" data-requestMappingFromServer="false" data-connectUrl="http://localhost:57481/dc7f1eca94044a1ca53edfa6de85d80f/browserLink"></script>
<!-- End Browser Link -->
<script src="/_framework/aspnetcore-browser-refresh.js"></script></body>
</html>
Related
[EDIT]
Ok, i unstertood that, if i render my class in a div with id="root" using ReactDOM.render it work and i can use console.log().
But i need that this component, that is in a Razor pages, could be receive ,as props, some data of the Razor's Model. (for example a list of users). So, i decided to use #Html.React to load the component. But if i use this method, i can pass properties but console.log() doesn't work.
What should i do?
And, there is a way which i can use, in the razor pages, the component as "" ??
[EDIT]
i want to do something like that but the component are not showing anymore.
<div id="root">
<App/>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
<script src="#Url.Content("https://unpkg.com/#babel/standalone/babel.min.js")"></script>
<script src="#Url.Content("~/js/app.jsx")" type="text/babel"></script>
i have an ASP.NET CORE MVC project and i want that my Razor pages implement ReactJS component.
I can load the component App but when i tried to use console.log it doens't work. I figure out that is because the component load only on server side but i can't find a correct way to allow my client-side to access to component and use the js to print in the console a value that i want.
First solution i tried was by follow this link: https://reactjs.net/features/server-side-rendering.html
But when it says to add :
#Scripts.Render("~/bundles/main")
#Html.ReactInitJavaScript()
I have 2 problem:
don't foud #Script so i had to install WebOptimize..but now it says that cannot fine the Ihtml string
i don't have this '~/bundles/main', what is that file? i have to install packages?
with ReactInitJavaScript component is showen but in the inspector says that component is undefined and in the class cannot find React.Component
So, the value are showen but i can't access to console. What i have to insert in the code to enable the client-side??
_Layout.cshtml:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - SportData</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/css/card.css" asp-append-version="true" />
</head>
<body>
<div class="container">
<main role="main" class="pb-3">
#RenderBody()
</main>
</div>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
#await RenderSectionAsync("Scripts", required: false)
</body>
</html>
Index.cshtml
#using Newtonsoft.Json;
#using SportData.Web.Models;
#using System.Web.Optimization;
#model SportContainer
#Html.React("App",new { Property1 = "value1", Property2 = "value2" })
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/1.7.1/remarkable.min.js"></script>
#Scripts.Render("~/bundles/main")
#Html.ReactInitJavaScript()
App.jsx:
class App extends React.Component{
componentDidMount() {
console.log('hi')
}
render() {
console.log(this.props)
const { Property1, Property2 } = this.props
const handler = (event) => {
console.log(event);
}
return (
<div>
<button onClick={handler}> clicca </button>
{console.log(this.props)}
<p>Property1: {Property1}</p>
<p>Property2: {Property2}</p>
<div className="box">Sono un box</div>
</div>
);
}
}
Program.cs:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddMvc().AddRazorRuntimeCompilation();
//builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddReact();
builder.Services.AddHttpContextAccessor();
builder.Services.AddJsEngineSwitcher(option => option.DefaultEngineName = V8JsEngine.EngineName).AddV8();
var app = builder.Build();
// configure middleware
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseReact(config => {
config.AddScript("~/js/App.jsx");
});
ReactSiteConfiguration.Configuration.JsonSerializerSettings.ContractResolver = new DefaultContractResolver();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
you have to use react js with api this is way.because if you will use react js like this you cannot make rich ui and also issues with the packges but if you want to use like this so you have to use like this.
check here
I used gatsby-plugin-google-gtag earlier in my gatsby project to add 2 Google Analytics tracking ID and it was working fine but unfortunately, my project already has gatsby-plugin-google-analytics which doesn't support multiple tracking ID like the gtag plugin shows in docs. So I found an article where they say to put it inside the html.js file so in the docs here of Customizing-html.js i copied my file to src/ using cp .cache/default-html.js src/html.js now I want to know where to put the script which I got from google analytics... Also, I have react-helmet installed.. so which way to use to put script?
manually in head? like so -
import React from "react";
import PropTypes from "prop-types";
export default function HTML(props) {
return (
<html {...props.htmlAttributes}>
<head>
<meta charSet="utf-8" />
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
{props.headComponents}
<script
async
src="https://www.googletagmanager.com/gtag/js?id=UA-123456789-1"
/>
<script
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-123456789-1');
`,
}}
/>
</head>
<body {...props.bodyAttributes}>
{props.preBodyComponents}
<div
key={`body`}
id="___gatsby"
dangerouslySetInnerHTML={{ __html: props.body }}
/>
{props.postBodyComponents}
</body>
</html>
);
}
HTML.propTypes = {
htmlAttributes: PropTypes.object,
headComponents: PropTypes.array,
bodyAttributes: PropTypes.object,
preBodyComponents: PropTypes.array,
body: PropTypes.string,
postBodyComponents: PropTypes.array,
};
OR tbh Idk where in html.js I have to insert this.. in body maybe?
<Helmet>
{/* other stuff... */}
{/* Global site tag (gtag.js) - Google Analytics */}
<script async src={`https://www.googletagmanager.com/gtag/js?id=${googleAnalyticsId}`}></script>
<script>
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', "${googleAnalyticsId}");
`}
</script>
</Helmet>
Would appreciate any help or article links to read from, as i'm very new to google analytics.. I already have one tracking code in my gatsby.config.js file like so { resolve: "gatsby-plugin-google-analytics", options: { trackingId: "UA-123456789-3", head: true, anonymize: true }, }, just need help putting the 2nd tracking code in.
Google Analytics script should be added inside the <head> tag. Ideally, this is automatically handled by the plugins. In fact, it's exactly what {props.headComponents}, {props.preBodyComponents} and {props.postBodyComponents} does, they manipulate Gatsby's SSR API onRenderBody to place the scripts you add in the gatsby-config.js or manually in the gatsby-ssr.js.
If you are not able to add several instances of gatsby-plugin-google-analytics or add multiple tracking identifiers using Google Tag Manager, you can use the html.js as you are doing. In this case, you should do something like:
import React from "react";
import PropTypes from "prop-types";
export default function HTML(props) {
return (
<html {...props.htmlAttributes}>
<head>
<meta charSet="utf-8" />
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
{props.headComponents}
<script
async
src="https://www.googletagmanager.com/gtag/js?id=UA-123456789-1"
/>
<script async src={`https://www.googletagmanager.com/gtag/js?id=${googleAnalyticsId}`}></script>
<script>
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', "${googleAnalyticsId1}");
`}
</script>
<script>
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', "${googleAnalyticsId2}");
`}
</script>
</head>
<body {...props.bodyAttributes}>
{props.preBodyComponents}
<div
key={`body`}
id="___gatsby"
dangerouslySetInnerHTML={{ __html: props.body }}
/>
{props.postBodyComponents}
</body>
</html>
);
}
HTML.propTypes = {
htmlAttributes: PropTypes.object,
headComponents: PropTypes.array,
bodyAttributes: PropTypes.object,
preBodyComponents: PropTypes.array,
body: PropTypes.string,
postBodyComponents: PropTypes.array,
};
Because you already have access to the <head> tag directly, there's no reason to use Helmet component, which purpose is to expose and add inside the <head> tag whatever wraps in any component. In this case, you have access directly to it so just add it there.
Once done, and because you are adding the tracking identifier manually, you can get rid of gatsby-plugin-google-analytics and the related unused plugins.
My component looks like this:
import React from "react"
function about(props) {
return (
<>
<h2>List users:</h2>
<ul>
{props.users.map((user) => {
return <li>{user.name}</li>
})}
</ul>
</>
)
}
export default about
export async function getStaticProps() {
console.log("Pedido GSP")
const res = await fetch("https://jsonplaceholder.typicode.com/users")
const users = await res.json()
return {
props: {
users,
}, // will be passed to the page component as props
revalidate: 60
}
}
My generated HTML file after build looks like these:
<!DOCTYPE html>
<html>
<head>
<meta charSet="utf-8"/>
<meta name="viewport" content="width=device-width"/>
<meta name="next-head-count" content="2"/>
<link rel="preload" href="/_next/static/css/120f2e2270820d49a21f.css" as="style"/>
<link rel="stylesheet" href="/_next/static/css/120f2e2270820d49a21f.css" data-n-g=""/>
<noscript data-n-css=""></noscript>
<script defer="" nomodule="" src="/_next/static/chunks/polyfills-a40ef1678bae11e696dba45124eadd70.js"></script>
<script src="/_next/static/chunks/webpack-93d688579f639ac646b4.js" defer=""></script>
<script src="/_next/static/chunks/framework-fb2dd7aba3784ca05084.js" defer=""></script>
<script src="/_next/static/chunks/main-89e612c37cd79392e22d.js" defer=""></script>
<script src="/_next/static/chunks/pages/_app-fd5464216d5252770dc3.js" defer=""></script>
<script src="/_next/static/chunks/pages/GSSP-43e12c3600ead54767ee.js" defer=""></script>
<script src="/_next/static/zNXWEGrv_m38JDMSXfB2l/_buildManifest.js" defer=""></script>
<script src="/_next/static/zNXWEGrv_m38JDMSXfB2l/_ssgManifest.js" defer=""></script>
</head>
<body>
<div id="__next"></div>
<script id="__NEXT_DATA__" type="application/json">
{"props":{"pageProps":{"users":[{"id":1,"name":"Leanne Graham","username":"Bret","email":"Sincere#april.biz","address":{"street":"Kulas Light","suite":"Apt. 556","city":"Gwenborough","zipcode":"92998-3874","geo":{"lat":"-37.3159","lng":"81.1496"}},(...),"page":"/GSSP","query":{},"buildId":"zNXWEGrv_m38JDMSXfB2l","isFallback":false,"gssp":true,"scriptLoader":[]}
</script>
</body>
</html>
For what I've been learning the <div id="__next"></div> should'nt be empty, it should contain the list of users already rendered.
The page loads normally, but I believe the list is being created on the browser instead of being on the server. I'm new to Next and I got to this result while merging the project with Redux.
Also why are so many <script> tags being generated at the begining?
Thanks in advance.
Well I got it working and came here to help others that might have the same problem.
If you're using Redux with redux-persist, the PersistGate is causing the issue. Pass the store with a Provider and the issue is gone (the store will still persist).
I have a NextJS site and recently implemented CookieBot. The CookieBot seems to be blocking the dynamically generated NextJs scripts before the cookies are accepted. When I add data-blockingmode=" manual" to the cookiebot script, it works fine. I want to add the data-cookieconsent='ignore' attribute to dynamically generated scripts so it doesn't block them.
I am not exactly sure how can I pass that attribute to dynamically Nextjs scripts. Also, if there is a fix that can be made from a CookieBot, happy to learn about that as well.
Also, I am not sure about the consequences of changing data-blockingmode="auto" to manual.
Below is the file _document.js
import React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
class appDoc extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx);
return { ...initialProps };
}
render() {
return (
<Html>
<Head>
<script
id='Cookiebot'
src='https://consent.cookiebot.com/uc.js'
data-cbid='id'
data-blockingmode='auto'
type='text/javascript'
></script>
<script
data-cookieconsent='ignore'
dangerouslySetInnerHTML={{
__html: `window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments)
}
gtag("consent", "default", {
ad_storage: "denied",
analytics_storage: "denied",
wait_for_update: 500,
});
gtag("set", "ads_data_redaction", true);`
}}
></script>
<script
data-cookieconsent='ignore'
dangerouslySetInnerHTML={{
__html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXX');`
}}
></script>
<meta name='google-site-verification' content='XXXXXX' />
</Head>
<body>
<Main />
<NextScript />
{/* !-- Google Tag Manager (noscript) --> */}
<noscript>
<iframe
src='https://www.googletagmanager.com/ns.html?id=GTM-xxxxxx'
height='0'
width='0'
style={{ display: 'none', visibility: 'hidden' }}
></iframe>
</noscript>
{/* <!-- End Google Tag Manager (noscript) --> */}
</body>
</Html>
);
}
}
export default appDoc;
I would like to include jquery.min.js and add a external JavaScript file and call a JavaScript function inside an existing react JS file.
I did below but it is not working
const VoCaaSComponentbtn = (
<React.Fragment>
<div>
<script type="text/javascript"src="https:xxxx/jquery-3.3.1.min.js"></script>
<script type="text/javascript"src="https:xxx/microsurvey" defer="defer"></script>
<div id="microsurvey" module="true" tab-info="tabname"></div>
<script type="text/javascript"> voc_getsurvey(); </script>
</div>
</React.Fragment>
);
You can import all the scripts in the main HTML file.
If you want to import the script inside the react component, you can use the following options.
Option 1: Use plain Javascript and React custom hook
Create custom hook [useScript.js]
import { useEffect } from 'react';
const useScript = url => {
useEffect(() => {
const script = document.createElement('script');
script.src = url;
script.async = true;
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, [url]);
};
export default useScript;
Use
import useScript from 'hooks/useScript';
const MyComponent = props => {
useScript('https://use.typekit.net/foobar.js');
// rest of your component
}
Option 2: Use plain Javascript in ComponentDidMount
componentDidMount () {
const script = document.createElement("script");
script.src = url;
script.async = true;
document.body.appendChild(script);
}
Option 3: Use dangerouslySetInnerHTML
const codeStr = `
<div>
<script type="text/javascript"src="https:xxxx/jquery-3.3.1.min.js"></script>
<script type="text/javascript"src="https:xxx/microsurvey" defer="defer"></script>
<div id="microsurvey" module="true" tab-info="tabname"></div>
<script type="text/javascript"> voc_getsurvey(); </script>
</div>
`
<div dangerouslySetInnerHTML={{ __html: codeStr }} />
You can add External JS library in indeex.html page inside public directory.
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<script type="text/javascript"src="https:xxxx/jquery-3.3.1.min.js"></script>
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
One another way to add external JavaScript file. If you only want to add for specific page or component.
componentDidMount() {
var script = document.createElement('script')
script.src = // path of external javascript file.
script.class = "external-script"
document.body.appendChild(script);
}