The Goal: I have a Next JS website with lots of pages. Some pages will have specific OG Share images for that page for Facebook etc. but some won't have specific images and will just use a generic or globally set share image.
The Problem: Setting a global share image within _app.js works great and gives every page a share image. Setting a share image for a specific page also works and adds a OG Image tag in Head. The problem now is there are two tags for an image, the global one and page specific one. Obviously Facebook doesn't know which one is best and just uses the first (global) one.
Possible Solutions:
Currently I have removed the global tags and will be setting each page individually which isn't ideal. It would be nice to know a page will always have a share image as a fallback.
When adding a page specific image tag overwrite/remove the globally set one.
Position the page specific image tag above the global tag in Head.
Somehow only add the global tag if a page specific tag isn't found.
Would love know if anyone has had the same issue and what you did!
To prevent duplicate tags, give each meta tag a key as explained here in the documentation. When you do this, Next will prioritize them as your pages load and only include the one from the page, or if none exists on the page with that key, then it will fall back to the one in _app.js.
Consider the following pages:
// pages/_app.js
import Head from 'next/head'
function MyApp({ Component, pageProps }) {
return (
<div>
<Head>
<meta property="og:title" content="Our Company Website" key="title" />
</Head>
<Component {...pageProps} />
</div>
)
}
// pages/about.js
import Head from 'next/head'
export default function AboutPage() {
return (
<div>
<Head>
<meta property="og:title" content="About Us" key="title" />
</Head>
<p>Learn about us</p>
</div>
)
}
// pages/contact.js
import Head from 'next/head'
export default function ContactPage() {
return (
<div>
<p>Send us an email</p>
</div>
)
}
In the above structure, the "contact" page will fallback to and show the "Our Company Website" meta tag found in _app.js because it does not have a meta tag of its own with the same key but the "about" page will have the "About Us" meta tag because it has the title key meta tag which will take priority over the one in _app.js.
Related
I was trying to implement a Facebook share button using dynamic meta tags in react, to share articles from my website. Unfortunately, I'm having a hard time showing the image card of the article in the Facebook post - it only shares the URL. However, when I replace the URL meta tag with the URL of the image for example www.mywebsite/Images/myImage.jpg, Facebook shows the image as wanted. I was wondering if there is a way to still use the URL of the image, but redirect this URL to that of the article every time it's clicked.
If anyone knows the answer to this, I'd appreciate some help a lot!
This is how I'm declaring my URL for the url meta tag:
const currentURL = window.location.href;
const from = window.location.href.indexOf('image');
const fullurl = window.location.href.slice(from + 6);
...
<meta property="og:url" content={fullurl}/>
<meta property="og:image" content={fullurl}/>
...
<FacebookShareButton className="mt-5 mb-3" windowWidth="800"
url={`${fullurl}`}
>
<FacebookIcon size={32} round={true} />
</FacebookShareButton>
That is, I'm trying to find a way to redirect from fullurl to currenturl every time it's clicked, but still, use it for the meta tags.
Material-UI adds generated style tags to the <header /> which is of course a standard place for styles, however I need my style tags to be added in a different html element.
I'm looking for a way to transition a legacy CodeIgniter PHP application to React. I have a plan but the issue is that this legacy application is using bootstrap which is messing with my React components.
The plan is to reset all styles in a div and render React components in it. something like:
<div class="clearcss">
<div>
<style type="text/css"></style> // material ui style tags
<div id="react-component"></div>
</div>
</div>
Unfortunately because Material ui adds all of its styles to the header Material ui styles are also reset, but if I could change where material ui places style tags then I think I could make it work.
Actually, in JSS documentation I found examples that show how to specify insertion points outside <head />.
Together with Ryan's comment pointing to material ui documentation I was able to achieve what I wanted.
JSS supports two ways of specifying a custom insertion point for styles:
By adding an html comment (e.g. <!-- custom-jss-insertion-point -->). This is only supported for insertion points in the <head>.
By specifying an element (e.g. insertionPoint: document.getElementById("custom-jss-insertion-point")). This approach supports insertion points in the document body.
Here's a working example of what is needed for the second approach:
index.html -- add an element that styles will be inserted after
...
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="custom-jss-insertion-point"></div>
<div id="root"></div>
</body>
...
App.js -- Tell JSS about the custom insertion point
import React from "react";
import { create } from "jss";
import { StylesProvider, jssPreset } from "#material-ui/core/styles";
import Button from "#material-ui/core/Button";
const jss = create({
...jssPreset(),
// Define a custom insertion point that JSS will look for when injecting the styles into the DOM.
insertionPoint: document.getElementById("custom-jss-insertion-point")
});
export default function App() {
return (
<StylesProvider jss={jss}>
<div className="App">
<Button variant="contained" color="primary">
Hello
</Button>
</div>
</StylesProvider>
);
}
This results in the styles being added as shown in the image below:
If you render the insertion point element using React, you need to ensure that the element exists before you try to call document.getElementById("custom-jss-insertion-point") while configuring JSS. If it is possible to do so, I would recommend rendering the insertion point element outside of React (as in the example) to avoid order-of-operations complications.
I'm using Gatsby to build a website that has a "specials" page with embedded Facebook. The Facebook embed does not display unless I manually reload the page or go directly to the "specials" page (rather than navigating to "specials" from the home page).
I have the Facebook script in my layout.js component file using React-Helmet:
export default ({ children }) => {
return (
<div id={layoutStyles.body}>
<Helmet>
// ...other tags
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v5.0"></script>
</Helmet>
<Navigation />
<div id={layoutStyles.main}>{children}</div>
<Footer />
</div>
)
}
And in my specials.js file I have the rest of the code for embedding:
// ...
render() {
return (
<Layout>
<div id="fb-root"></div>
<p>Scroll to see more specials.</p>
<div id={styles.facebook} className="fb-page" data-href="https://www.facebook.com/LakesideMarcell/" data-tabs="timeline" data-width="500" data-height="" data-small-header="true" data-adapt-container-width="true" data-hide-cover="false" data-show-facepile="true"><blockquote cite="https://www.facebook.com/LakesideMarcell/" className="fb-xfbml-parse-ignore">Lakeside Lumber & Hardware LLC</blockquote>
</div>
<p>If you don't see specials here click the link above to see our specials on Facebook.</p>
</Layout>
)
}
}
export default Specials
I've tried moving the script tag around in the code but the result is the same problem. I also tried using componentDidMount with state, and a function that called window.location.reload(), but I cold not get the page to reload only once.
I've used the same code embedded in a version of the website not using Gatsby and I don't have this issue so it must be something to do with Gatsby. Is there a way to fix this or reload the page once without user action?
Suppose I open one url for eg.: "https:www.xyz.com" in new window using reactJs. Now when I visit the link, it will show https:www.xyz.com in the title bar.I need to rename the title-bar with different name eg.: "new tab opened".I tried using Helmet tag but it works for main page.But what I want is the new link which opens should get changed.What should I do ?
You can use react-helmet to update the page title dynamically in react apps.
import {Helmet} from "react-helmet";
....
render(){
return(
<div>
<Helmet>
<title>New Tab Opened</title>
<meta name="description" content="New Tab Component" />
</Helmet>
// Your component code here...
</div>
)
}
Refer the docs here.
Hi I am developing a website using reactjs. Each page of the website has mainly 3 parts (1. header 2. body 3. footer) . So header and footer will be same for each page and body will keep on changing. Should I create header and footer components and then include them in each page of the website. Is this good design?
How can I highlight navigation menu option for a particular page. For example If I am on contactus page then ContactUs menu option should be highlighted. Similarly If I am one Home Page then "Home" should be highlighted.
In react apps you usually use a router library for this.
A router also takes care of the url in the address bar, so you can save and share links to sub pages in a single page application, and use the browser's back button.
The most popular router for react is called "React Router", but there are other alternatives. It's even possible to write your own router.
React-router's docs has examples of how you can implement this. For the highlighting effect, you can use the component called <NavLink />
Instead of including the header and footer in each page, you start from the outside in. You only put header and footer in once, typically in a main <App />, and then include variable page content inside <Route /> components.
yes you can create 2 components on the top level. they will be header and footer. for navigation; you can use react-router. it will be used to navigate between views. you can put the body component inside your header component your main App structure can be :-
<App>
<HeaderComp/>
<FooterComp/>
</App>
now you can set react-router to change the component being render in body place when any link in the header is clicked. you can also keep the state of currently active view and highlight its color when active.
in react-router v4 you can use switch and route to change between components
<Switch>
<Route exact path='/' component={YourComponent} />
<Route path='/secondcomponent' component={YourSecondComponent} />
<Route path='/thirdcomponent' component={YourthirdComponent} />
</Switch>
this will be your body component , other components like given above will be shown when you click on the link in the head that matches the path in Route tag.
now you header render can be like this.
render(){
return (
<div>
<TopBar/>
<BodyComp/>
<div/>
)
}
the topbar will be fixed and stay on top , the body will have all the space except the margin on top to adjust below the topbar
your topbar can be like this.
render(){
return(
<div className="topBarcontainer">
<Link to="/" >
<div className ="topBarItem">
Home
</div>
</Link>
<Link to="/secondComponent" >
<div className ="topBarItem">
secondComponent
</div>
</Link>
</div>
)
}
as for you want to highlight the current view , you can keep the state array and add give each Link the value from that array , and put onMouseDown on it , when it is clicked it will callback telling the value that is clicked and u will reset all the items background color to default , then you can set the style of that particular active item in your header to active color. you should use inline styling for that instead of className