Dynamic link previews with React helmet in ReactJS - reactjs

Does anyone know if there's a possibility to set truly dynamic meta tags per page in a React App without Server Side Rendering?
In a project that I am building I have some pages with a route like / article / {Id} and I would like to define dynamic meta tags (title, image, description). I use a reaction helmet as a component but it doesn't work here is the code of my component, part of the code page article / {id}, and my page index.html
index.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta property="og:title" content="title" data-rh="true">
<meta property="og:description" content="description" data-rh="true">
<meta property="og:image" content="icon%20maracana%20app.png" data-rh="true">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css" />
<link href="https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic" rel="stylesheet"
type="text/css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-173374516-1"></script>
<script data-ad-client="ca-pub-7237319988145838" async
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'UA-173374516-1');
</script>
<!-- <script type="text/javascript" src="js/my_script.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/​moment.js/2.19.1/moment.min.js"></script>
</head>
<body>
<!-- Plugin Comments -->
<div id="fb-root"></div>
<script async defer crossorigin="anonymous"
src="https://connect.facebook.net/fr_FR/sdk.js#xfbml=1&version=v9.0&appId=357191748915887&autoLogAppEvents=1"
nonce="QVCodNV8"></script>
<!-- ---------------- -->
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
component:
import React from "react";
import PropTypes from "prop-types";
import { Helmet } from "react-helmet";
import { IMAGES_LINK, API_LINK } from '../../utils/constants'
//const metaDecorator = require("../../data/metaDecorator");
const MetaDecorator = ({ title, description, imageUrl, imageAlt }) => {
if (title != undefined & description != undefined & imageUrl != undefined & imageAlt != undefined) {
return (
<Helmet>
<title>{title}</title>
<meta property="og:title" content={title} />
<meta name="description" content={description} />
<meta property="og:description" content={description} />
<meta property="og:image" content={API_LINK + imageUrl} />
<meta
property="og:url"
content={"https://maracanafoot.com" + window.location.pathname + window.location.search}
/>
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image:alt" content={imageAlt} />
{/* <meta name="twitter:site" content={metaDecoratortwitterUsername} /> */}
</Helmet>
);
} else {
return (
<Helmet>
</Helmet>
);
}
}
MetaDecorator.propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
imageUrl: PropTypes.string.isRequired,
imageAlt: PropTypes.string.isRequired,
};
export default MetaDecorator;
article page :
render = () => {
const s = this.state;
return (<>
<div>
{this.state.loadingArticle ? <>
<br />
<div style={this.styleSpinner} className='mt-3 mb-3'>
<ImpulseSpinner size={30} color="#208FDF" loading={this.state.loadingArticle} />
</div></>
: null}
{!this.isEmpty(this.state.article) ? <>
<MetaDecorator
description={this.state.article.resumer}
title={this.state.article.title}
imageUrl={this.state.article.image}
imageAlt="image alt"
/>
Thanks in advance for any hint!

Related

React Portal error "Target Container is not a DOM element"

Getting an error with React portal in the production build but none in development. I'm getting error #200 "target container is not a DOM element". I have put my code below. Please ignore the CSS part.
import ReactDOM from 'react-dom'
import React from 'react'
const Modal_Styles={
backgroundColor:'#FFF',
position:'fixed',
top:'50%',
left:'50%',
right:'10%',
bottom:'10%',
padding:50,
textAlign:'justify',
transform:'translate(-50%,-50%)',
borderRadius:'12px',
zIndex:1000
}
const Overlay_Styles={
position:'fixed',
left:0,
top:0,
right:0,
bottom:0,
backgroundColor:'rgba(0,0,0,0.3)',
zIndex:1000,
}
export default function Modal({open,children,onClose}) {
if(!open){return null}
return ReactDOM.createPortal(
<>
<div style={Overlay_Styles}>
<div style={Modal_Styles}>
{children}
<button className='mbutton' onClick={onClose}>x</button>
</div>
</div>
</>,
document.getElementById('portal')
)
}
The index.html file is:
<!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="C"
/>
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<div id="portal"></div>
</body>
</html>
Any suggestions?
The names for both divs root and portal are correctly written in the index.js and modal.js.

how to render react router in Laravel

I am sure this has been asked before but I haven't found the answer when browsing here or google.
I am following this guide to do a react-router-dom based menu in Laravel -> https://laravel-reactjs.com/react-sidebar-navigation-menu-tutorial-beginner-react-js-project-using-hooks-router/
I understand the guide, and are also aware of that Switch has been replaced with routes in newer version of react-router.
My question is how render the navigation in my blade file. I have tried multiple ways of render, ReactDom.render and appending to elements.. I can't get it to work.
My code is
routepath.js
import ReactDom from 'react';
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Navbar from "./components/Navbar";
function App() {
return(
<Router>
<Navbar />
<routes>
<route path='/' />
</routes>
</Router>
);
}
export default App;
navbar.js
import * as FaIcons from "react-icons/fa";
import { Link } from 'react-router-dom';
function Navbar() {
return (
<div className="navbar">
<link to="#" className="menu-bars">
<FaIcons.FaBars />
Menu
</link>
</div>
)
}
export default Navbar
app.js (to compile)
require("./components/main"); //FullCalendar
require("./RoutePath");
app.blade.php
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Tasksman</title>
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<div id="menu"></div>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
My file structure is
- js
- Components
- Navbar.js
- pages
- Home.js
- Products.js
- Reports.js
- app.js
- RoutePath.js
- views
- app.blade.php
Try this code
Route::view('/{path?}', 'app')
->where('path', '.*')
->name('react');
in view file
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Tasksman</title>
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
in mix file
mix.js('resources/js/index.js', 'public/js')
.react()
.less('resources/sass/app.scss', 'public/css');

Typescript React Target container is not a DOM element

I have an addin for outlook, which is complaining: Uncaught Invariant Violation: Target container is not a DOM element.
My app already ran before, so it seems to be an issue within my components (just a guess).
The Exception occours here:
const render = Component => {
ReactDOM.render(
<AppContainer>
<Component title={title} isOfficeInitialized={isOfficeInitialized} key="config" />
</AppContainer>,
document.getElementById("root")
);
};
<!doctype html>
<html lang="en" data-framework="typescript">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Contoso Task Pane Add-in</title>
<!-- Office JavaScript API -->
<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
<!-- For more information on Office UI Fabric, visit https://developer.microsoft.com/fabric. -->
<link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/9.6.1/css/fabric.min.css"/>
<!-- Template styles -->
<link href="../taskpane/taskpane.css" rel="stylesheet" type="text/css" />
</head>
<body class="ms-font-m ms-Fabric">
<div id="root"></div>
</body>
</html>
EDIT: Rendered code in Chrome debug tools
How can I find the code part which cannot be rendered? Which DOM element might be the issue?

Can't see meta tags on source code using Helmet

I can't see my meta tags on my source code.
I see my tags only when I inspect my page on Elements . Is it enough to show meta tags in elements to correctly register my page on search engines?
I'm using React Helmet without a server.
Home page:
import {Helmet} from 'react-helmet';
export default class Home extends Component {
render() {
return (
<div>
<Helmet>
<meta charSet="utf-8" />
<title>Home</title>
<link rel="canonical" href="https://somedomain.com/" />
<meta name="description" content="Description here ......." />
</Helmet>
......
My index.html file:
<!DOCTYPE html>
<html lang="en">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<head>
</head>
<body>
<div id="root"></div>
</body>
</html>
Output inspect Elements:
<title>Home</title>
<link rel="canonical" href="https://somedomain.com/" data-react-helmet="true">
<meta charset="utf-8" data-react-helmet="true">
<meta name="description" content="Description here ......" data-react-helmet="true">
Output Source code:
<!doctype html><html lang="en"><link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link rel="manifest" href="/site.webmanifest"><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5"><head><link href="/static/css/2.69121389.chunk.css" rel="stylesheet"><link href="/static/css/main.8a7e4572.chunk.css" rel="stylesheet"></head><body><div id="root"></div><script>!function(e){function t(t){for(var n,i,l=t[0],f=t[1],a=t[2],c=0,s=[];c<l.length;c++)i=l[c],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&s.push(o[i][0]),o[i]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(p&&p(t);s.length;)s.shift()();return u.push.apply(u,a||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,l=1;l<r.length;l++){var f=r[l];0!==o[f]&&(n=!1)}n&&(u.splice(t--,1),e=i(i.s=r[0]))}return e}var n={},o={1:0},u=[];function i(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=e,i.c=n,i.d=function(e,t,r){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(i.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)i.d(r,n,function(t){return e[t]}.bind(null,n));return r},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="/";var l=this["webpackJsonpmy-website"]=this["webpackJsonpmy-website"]||[],f=l.push.bind(l);l.push=t,l=l.slice();for(var a=0;a<l.length;a++)t(l[a]);var p=f;r()}([])</script><script src="/static/js/2.c77f8540.chunk.js"></script><script src="/static/js/main.69bc3bde.chunk.js"></script></body></html>

Initializing materialize in react apps

I am new to ReactJS. So I have a straight forward question.
I have used materialize cdn, included in index.html. But when I try to initialize it in my component it says 'M' not defined. Where should I initialize the same.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.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>
My component looks something like this
import React from "react";
class Dashboard extends React.Component {
componentDidMount() {
document.addEventListener("DOMContentLoaded", function() {
var elems = document.querySelectorAll(".carousel");
var instances = M.Carousel.init(elems, options);
});
}
}
export default Dashboard;
CodeSandbox link: - https://codesandbox.io/s/40jvz6j590
Well, if you are using it, you need to import it :D
import React from "react";
import {Carousel} from "react-materialize";
And here is how to use it https://react-materialize.github.io/#/carousel

Resources