Open Graph not displaying properly on Twitter [duplicate] - html

I am trying to fetch content from an API and show it in a page. It's working fine but when I am trying to view page source code it's not showing those content that I am getting from API. I am using Next.js for this project and the code that I have used is following. Is there anyone who can help help me to solve this issue?
import React, { Fragment, useEffect, useState } from 'react'
import { API_BASE_URL } from '../Config/Settings'
import SideBar from '../Layouts/SideBar'
import Link from "next/link"
import Head from 'next/head'
import styles from '../styles/Home.module.css'
import axios from 'axios'
export const CmsPage = (props) => {
const [PageHtmlContent, setPageContent] = useState('');
const [PageTitle, setPageTitle] = useState('');
const [PageDescription, setPageDescription] = useState('');
const [SeoKeyword,setSeoKeyword]=useState('');
useEffect( async() => {
let body = {pageTypeCode:props.pageType,pageName:props.pageName};
const config = {
headers: {
'x-auth-token':"rpsite-public-token"
}
}
try {
const res= await axios.post(API_BASE_URL+'/api/cms/page',body,config);
// alert(res.data.content);
setPageContent(res.data.content);
setPageTitle(res.data.seoTitle);
setPageDescription(res.data.seoDescription);
setSeoKeyword(res.data.seoKeyword);
}
catch(err) {
setPageContent('<b>Something went wrong!</b>');
}
},[props]);
return (
<section class="inner-body-section">
<Head>
<title>{PageTitle}</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<meta name="keywords" content={SeoKeyword} />
<meta name="description" content={PageDescription}/>
</Head>
<div class="container">
<div class="row">
<div class="col-md-3">
<SideBar/>
</div>
<div class="col-md-9">
<div className="inner-body-content">
<div id="contentBlock" className="page-content" dangerouslySetInnerHTML={{__html:PageHtmlContent}}></div>
</div>
</div>
</div>
</div>
</section>
)
}
export default CmsPage;

What you get when looking at View Page Source is the HTML returned by the server.
Because you're making the request and populating the data inside a useEffect this will only occur on the client, thus the data won't be visible in the page's source.
If you want the data to be populated on the server you may want to have a look at getStaticProps or getServerSideProps instead.
Here's an example of how you can use getStaticProps to populate the data on the server-side (a similar approach could be used with getServerSideProps).
export async function getStaticProps(context) {
const res = await axios.post(`${API_BASE_URL}/api/cms/page`);
// Assuming `res.data` format: { content, seoTitle, seoDescription, seoKeyword }
return {
props: res.data
};
}
const CmsPage = ({ content, seoTitle, seoDescription, seoKeyword }) => {
return (
<>
<Head>
<title>{seoTitle}</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<meta name="keywords" content={seoKeyword} />
<meta name="description" content={seoDescription}/>
</Head>
<section class="inner-body-section">
<div class="container">
<div class="row">
<div class="col-md-3">
<SideBar/>
</div>
<div class="col-md-9">
<div className="inner-body-content">
<div id="contentBlock" className="page-content" dangerouslySetInnerHTML={{__html: content}}></div>
</div>
</div>
</div>
</div>
</section>
</>
)
}
export default CmsPage;

Related

Data passing probelm between files in next js

So i have three files here :-
project.js
import Image from 'next/image';
import Link from 'next/link'
import { DATA } from '../../components/Data'
const WEB_RELATED = []
const PC_EXES = []
for(let i=0;i<DATA.length; i++){
if(DATA[i]['loc'] == 'WEB'){
WEB_RELATED.push(DATA[i])
}
else if(DATA[i]['loc'] == 'EXE'){
PC_EXES.push(DATA[i])
}
}
const WEB = WEB_RELATED.map(item =>
<div className="PROJECTS_Projects">
<div className="PROJECTS_Projects_Image">
<Image
className='PROJECTS_Projects_image'
src={item['img']}
layout='fill'
// objectFit='contain'
/>
</div>
{/* if someone clicks on this link i want them to go to [project].js and send This item to [projcet].js */}
<Link href={'/projects/' + WEB_RELATED.indexOf(item)}>
<a>{item['title']}</a>
</Link>
<p>{item['desc']}</p>
</div>
);
const PC = PC_EXES.map(item =>
<div className="PROJECTS_Projects">
<div className="PROJECTS_Projects_Image">
<Image
className='PROJECTS_Projects_image'
src={item['img']}
layout='fill'
// objectFit='contain'
/>
</div>
{/* if someone clicks on this link i want them to go to [project].js and send This item to [projcet].js */}
<Link href={'/projects/' + PC_EXES.indexOf(item)}>
<a>{item['title']}</a>
</Link>
<p>{item['desc']}</p>
</div>
);
export default function index() {
return (
<div className="PROJECTS_Container">
<div className="PROJECTS_Sub_Container">
<div className="PROJECTS_New">
<h1>Web-Related</h1>
<div className="PROJECTS_Present">
{WEB}
</div>
</div>
<div className="PROJECTS_New">
<h1>Pc apllications</h1>
<div className="PROJECTS_Present">
{PC}
</div>
</div>
</div>
</div>
)
}
Project Display page [project.js]
import { useRouter } from 'next/router'
import { useState } from 'react';
import Image from 'next/image';
import { DATA } from '../../components/Data';
import React, {useEffect} from 'react';
export default function title() {
const router = useRouter();
const { project } = router.query
const [state, setState] = useState()
// when user comes here i want the item sent to be read and injected into the html
useEffect(() => {
// project && console.log('value', project, 'length : ', project.length);
// setState(project)
console.log(DATA[project]['loc'])
}, [router])
return (
<div className='DISPLAY_Container'>
<div className="DISPLAY_Sub_Container">
<div className="DISPLAY_Image">
<Image
src={'/img/Projects/Cluq.PNG'}
layout='fill'
/>
</div>
<div className="DISPLAY_Info">
<h3>{state}</h3>
SUS
<p>lorem300</p>
</div>
</div>
</div>
)
}
DATA.JS file where i've kept all of the objects i want to be shown
export const DATA = [
{
'loc':'WEB',
'title':"Bukkit List",
'img':'/img/Projects/Bukkit-List.PNG',
'desc':"Bukkit-List is a easy to use and free task managing webapp, with password protection now!",
'fullDesc':""
},
{
'loc':'WEB',
'title':"SilenxIka-Github",
'img':'/img/Projects/SilenxIkaGithub.PNG',
'desc':"First github website for Project SilenxIka, which is completly made from vanilla HTML/CSS/JS",
'fullDesc':""
}
]
when someone presses a link in the first file (check there are coments above the link) the item in the link shall be passed to the second file and i can use the item in [project].js file to inject it into the html
You can append query parameters to your url and use the useRouter hook from "next/router" for getting the content of those query parameters in your other file.
Let's imagine your item object has an id and we want to append that id as a query parameter to your route:
In project.js:
export const arrayOfItems = [
{id: 'A', title: 'A title'},
{id: 'B', title: 'B title'},
{id: 'C', title: 'C title'},
{id: 'D', title: 'D title'},
];
// Add query param "item_id" plus the id of your item to your url (note the '?')
{arrayOfItems.map((item)=>
<Link href={'/projects?item_id= + item.id }>
<a>{item.title}</a>
</Link>
)
In your product display page:
import { useRouter } from "next/router";
import { arrayOfItems } from "./project.js"; // path to where array is exported from
const ProductPage = () => {
const router = useRouter();
useEffect(() => {
// here you have access to the query parameters
console.log(router.query?.item_id);
// get item_id from route
const routeItemId = router.query?.item_id;
// search through array and find item with matching id
const matchingItem = arrayOfItems.find((item)=> item.id === routeItemId && item);
console.log(matchedItem);
}, [router]);
return(<></>)
}

How to dynamically define nested routes in express/node.js

I'm pretty new to the express/nodejs and would like to apply a route such that routes are dynamically adapted based on the article name.
The articles are saved within articles.js consisting of
const articles = [{
title: 'article1',
link: 'article2',
creator: 'Anna',
createdAt: '17/10/2021',
description: 'Test description',
publish: 'True'
},
{
title: 'article2',
link: 'article2',
creator: 'Sascha',
createdAt: '17/10/2021',
description: 'Test description',
publish: 'True'
},
{
title: 'article3',
link: 'article3',
creator: 'Anna',
createdAt: '17/10/2021',
description: 'Test description',
publish: 'True'
}]
exports.articles = articles;
In a seperate file I'm defining my routes in index.js:
const express = require('express')
const router = express.Router()
//load arcticles
const Articles = require('../articles/articles');
// ----Routing----
router.get("/", async (req, res) => {
const articles = await Articles.articles.filter(all => all.publish ==='True')
res.render("index", {articles: articles});
});
router.get("/route1", async (req, res) => {
const articles = await Object.values(Articles.articles).filter(all => all.publish ==='True');
res.render("route1", {articles: articles});
});
router.get("/route1/:link", async (req, res, next) => {
const articles = await Object.values(Articles.articles).filter(all => all.publish ==='True');
var name = req.params.link;
return res.json({ message: 'Users Show', Articles: name});
});
module.exports = router
However, when trying to access these via my HTML file, this doesnt seem to work
<!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="description" content="" />
<meta name="author" content="" />
<title>Clean Blog - Start Bootstrap Theme</title>
<link href="../css/styles.css" rel="stylesheet" />
</head>
<body>
<!-- Main Content-->
<div class="container px-4 px-lg-5">
<div class="row gx-4 gx-lg-5 justify-content-center">
<div class="col-md-10 col-lg-8 col-xl-7">
<!-- Post preview-->
<div class="post-preview">
<% articles.forEach(article => { %>
<h2 class="post-title" style="margin-bottom: -1.41rem"><%= article.title %></h2>
</div>
</div>
</div>
</div>
<!-- Footer-->
<footer class="border-top">
</footer>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<script src="js/scripts.js"></script>
</body>
</html>
I suppose that within the HTML file the routes cannot be catched properly, however I cannot tell how why this is the case.

Gatsby conditional className based on frontmatter

I'm trying to add a className of split to my header, based on the page template as defined in the frontmatter of a page. I've got a page template called split and want the header to have that class on pages that are utilizing the template. Here are my templates:
layout.js
import React from 'react'
import PropTypes from 'prop-types'
import Helmet from 'react-helmet'
import { StaticQuery, graphql } from 'gatsby'
import Header from './header'
import Footer from './footer'
import '../css/main.scss'
import favicon from './favicon.png'
const Layout = ({ children, frontmatter }) => (
<StaticQuery
query={graphql`
query PageInfoQuery {
site {
siteMetadata {
title
footer
}
}
markdownRemark {
frontmatter {
template
}
}
}
`}
render={data => (
<>
<Helmet
title={data.site.siteMetadata.title}
meta={[
{ name: 'description', content: 'Sample' },
{ name: 'keywords', content: 'sample, something' },
]}
link={[
{
rel: 'shortcut icon',
type: 'image/png',
href: `${favicon}`,
},
]}
>
<html lang="en" />
</Helmet>
<Header siteTitle={data.site.siteMetadata.title} frontmatter={data.markdownRemark.frontmatter}/>
{children}
<Footer footer={data.site.siteMetadata.footer} />
</>
)}
/>
)
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout
header.js
import PropTypes from 'prop-types'
import React from 'react'
import Navbar from './navbar'
const Header = ({ siteTitle, frontmatter }) => (
<header className={ frontmatter.template === 'split' ? 'header split' : 'header' }>
<section className="navigation">
<Navbar siteTitle={siteTitle} />
</section>
</header>
)
Header.propTypes = {
siteTitle: PropTypes.string,
}
Header.defaultProps = {
siteTitle: '',
}
export default Header
I know that I've got the data.markdownRemark.frontmatter working correctly, as in my template split.js I'm able to display the template name dynamically in the hero element, using {post.frontmatter.template}. In the interest of being thorough I'll include that as well.
split.js
import React from 'react'
import Helmet from 'react-helmet'
// eslint-disable-next-line
import { Link, graphql } from 'gatsby'
import Layout from '../components/layout'
// import blocks
import Feature from '../components/blocks/feature'
import Hero from '../components/blocks/hero'
class BlocksTemplate extends React.Component {
render() {
const post = this.props.data.markdownRemark
const siteTitle = this.props.data.site.siteMetadata.title
const siteDescription = post.excerpt
const heroImage = post.frontmatter.hero_image.childImageSharp.fixed.src
return (
<Layout location={this.props.location} title={siteTitle}>
<Helmet
htmlAttribute={{ lang: 'en' }}
meta={[{ name: 'description', content: siteDescription }]}
title={`${post.frontmatter.title} • ${siteTitle}`}
/>
<section className="hero" style={{ backgroundImage: `url(${heroImage})` }}>
<h4 className="name">
<Link to="/">
{this.props.siteTitle}
{post.frontmatter.template}
</Link>
</h4>
</section>
{post.frontmatter.blocks.map(block => {
switch (block.component) {
case 'feature':
return <Feature block={block} />
case 'hero':
return <Hero block={block} />
default:
return ''
}
})}
</Layout>
)
}
}
export default BlocksTemplate
export const pageQuery = graphql`
query SplitPageBySlug($slug: String!) {
site {
siteMetadata {
title
}
}
markdownRemark(fields: { slug: { eq: $slug } }) {
id
excerpt
html
frontmatter {
template
title
hero_image {
childImageSharp {
fixed(width: 1500) {
src
}
}
}
blocks {
component
image {
childImageSharp {
fixed(width: 1500) {
src
}
}
}
}
}
}
}
`
Here is the header markup that is being rendered; in essence the split class is never being added.
<header class="header">
<section class="navigation">
<nav class="nav" role="navigation">
<div class="branding">
<h6 class="name">Jesse Winton</h6>
</div>
Home
<a aria-current="page" class="" href="/about-the-demo">What is this?</a>
About Gatsby
Blog
</nav>
</section>
</header>
I'm fairly new to Gatsby, so any help would be very much appreciated! Thank you!
In layout.js, you are passing frontmatter={data.markdownRemark.frontmatter} to the header from the query above it in layout.js. This is a staticQuery which will always return the same data.
I see you are querying for the correct data in the pageQuery in split.js, but this data is not passed along to the layout in split.js:
<Layout location={this.props.location} title={siteTitle}>
One way to fix this is to pass the template name to the layout props, just like you are already doing with location and title attributes.
Another way would be using the gatsby-plugin-layout plugin which return the old behavior from V1 Gatsby for the Layout component, adding a layout wrapper to every component. Then you could the pageContext to the split component directly.

Cannot read property 'products' of undefined in React app

I get the error Cannot read property 'products' of undefined for my web app. the code for the property is shown below
import React from 'react';
import ProductItem from '../product-item/ProductItem';
import Title from '../../common/Title';
import { useProductState } from '../../../global-state';
export default function ProductList() {
// Accessing productState
const { productState } = useProductState();
const { products } = productState;
let productItems = products.map(product => (
<ProductItem key={product.id} product={product} />
));
return (
<div className="py-5">
<div className="container">
<Title name="Our" title="Menu" />
<div className="row">{productItems}</div>
</div>
</div>
);
}
Maybe you are fetching data from some api? If so, maybe when ProductList mounts products are not fetced yet. Try this:
export default function ProductList() {
// Accessing productState
const { productState } = useProductState();
const { products } = productState;
if(!products) { // if products initial value is an empty array use !products.length
return <div>Loading</div>
}
let productItems = products.map(product => (
<ProductItem key={product.id} product={product} />
));
return (
<div className="py-5">
<div className="container">
<Title name="Our" title="Menu" />
<div className="row">{productItems}</div>
</div>
</div>
);
}

React JS Accessing JSON as State

I'm completely brand new to React JS and am trying to create an application that will grab JSON data from a pokemon API, which I will then use to display on screen. Right now, I have it set up so that the user has to input the name of the pokemon they are looking for, i.e. pikachu, and when the search button is pressed, the application will make the API call to return the JSON. I've been searching for the past few days, and cannot seem to find anything to work with the way I currently have my code set up. How do I bind the JSON output to a component that I would then be able to display to the user?
Here's the js code (App.js)
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import ReactDOM from 'react-dom';
class App extends Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('Text field value is: ' + this.state.value);
fetch('https://pokeapi.co/api/v2/pokemon/'+this.state.value+'/')
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data.name +" "+ data.id);
});
}
)
.catch(function(err) {
console.log('Fetch Error :-S', err);
});
}
render() {
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<input type="text"
placeholder="enter name of pokemon here"
value={this.state.value}
onChange={this.handleChange}
/>
<button type="button" onClick={this.handleSubmit}>Search the Pokedex</button>
</div>
);
}
}
export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tag above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start`.
To create a production bundle, use `npm run build`.
-->
</body>
</html>
Screenshot of issue:
http://imgur.com/a/g9H5r
Try this
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import ReactDOM from 'react-dom';
class App extends Component {
constructor(props) {
super(props);
this.state = {
value: '',
data: {} //filled by fetch data from API
};
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('Text field value is: ' + this.state.value);
var _this = this;
fetch('https://pokeapi.co/api/v2/pokemon/'+this.state.value+'/')
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data.name +" "+ data.id);
_this.setState({data: data});
});
}
)
.catch(function(err) {
console.log('Fetch Error :-S', err);
_this.setState({data: {}});
});
}
render() {
var data = this.state.data;
return (
<div className="App">
<div className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h2>Welcome to React</h2>
</div>
<input type="text"
placeholder="enter name of pokemon here"
value={this.state.value}
onChange={this.handleChange.bind(this)}
/>
<button type="button" onClick={this.handleSubmit.bind(this)}>Search the Pokedex</button>
<h3>{data.id}</h3>
<h3>{data.name}</h3>
</div>
);
}
}
ReactDOM.render(App, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tag above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start`.
To create a production bundle, use `npm run build`.
-->
</body>
</html>