Next.js Link and paths - javascript

I have a popover menu in my header displaying products. When clicking on the first one, regardless of which one on the list, it navigates correctly to the path "products/some-product". But if I'm on one of the product pages already, and I'm trying to navigate to another product it adds the "products/" again in the URL. E.g. "products/products/some-product".
I'm using Next.js 11 and Link.
Below is part of my code handling the list of products with navigation:
<div>
{products.map((item) => (
<Link href={`products/${item.href}`}>
<a
key={item.name}
>
<div>
<item.icon
aria-hidden="true"
/>
</div>
<div>
<p>
{item.name}
</p>
<p>
{item.description}
</p>
</div>
</a>
</Link>
))}
</div>
I have a menuData.jsx component to keep track of all my products, which I then import to the file above. Here is an example from the menuData.jsx file:
export const products = [
{
name: "some-product",
description:
"Some description",
icon: CheckIcon,
},
]
Can you spot what I'm doing wrong? :)

Just add a / in front of products in the href:
<Link href={`/products/${item.href}`}>
You are linking to relative paths, which, when you are on /products, will be /products/products:

Related

IFrame not found with Next/Link-pagination

I have a page with an embedded iframe script I am using with the Next-script tag.
script-page.tsx
import Script from 'next/script';
import Layout from '~/common/layout/Layout';
const ScriptPage = () => {
return (
<Layout>
<div className="m-0 md:m-12">
<div id="embedded-pressroom" data-publisher="212312" />
<Script
type="text/javascript"
src="my-link"
/>
</div>
</Layout>
);
};
export default ScriptPage;
It is showing the content if I go directly into the href, i.e localhost:3000/p/script-page/ but it is not showing if I go into localhost:3000/p/home-page/ and navigate back to the script page.
This is my navbar:
import Link from 'next/link';
const Navbar = () => {
return (
<div className="px-6 md:pr-0 navbar-content">
<h2>Navigation</h2>
<ul>
<li>
<Link href="/home-page">
<a>Home</a>
</Link>
</li>
<li>
<Link href="/script-page">
<a>Script</a>
</Link>
</li>
</ul>
</div>
);
};
export default Navbar;
What is happening, why do I have to refresh the script-page in order for the content to be shown when navigating internally with Next-Link. It shows if I directly go in to the script page, but if I do:
Script Page
Navigate to Home Page
Go back to Script Page
I get "[iFrameSizer][Host page: embedded-pressroom-iframe] [Window focus] IFrame(embedded-pressroom-iframe) not found" in the console.
What can I do to fix this?

Opening url in json file with vue.js

I have a url key in my json file and there are values against it. When I create a button with vue.js and click this button, I want the url to be opened. How can I do it?
My code:
<template>
<div class="q-pa-md q-gutter-sm">
<q-btn #click="gotoUrl" color="white" text-color="black" label="Standard" />
</div>
</template>
<script>
import json from './assets/test.json'
export default defJson({
setup: () => ({jsonData}),
methods: {
gotoUrl(){
window.open()
}
}
})
</script>
Json file:
[
{
"id": "1",
"name": "stackoverflow",
"url": "https://stackoverflow.com/"
}
]
When I click this button, the link needs to be read and opened in the json file.
First you wan to loop over the objects in your JSON array like this:
<div v-for="site in jsonData" :key="site.id" class="q-pa-md q-gutter-sm">
...
</div>
Then you can simply create elements around your buttons with the url from the site in the href:
<div v-for="site in jsonData" :key="site.id" class="q-pa-md q-gutter-sm">
<a :href="site.url" target="_blank">
<q-btn color="white" text-color="black" :label="site.name" />
</a>
</div>
Its pretty basic vue stuff.. They have great documentation, check it out: https://vuejs.org/guide/introduction.html

How to have a link of js array and img src in React

I have a React component that maps data from a .js file, containing objects in the array. How can I link my title and images from within this function to access respective pages?
In this file, I am getting errors for every [x] used for linking img src to the info.js file
Is there a different way to link an img from a js array?
import React from "react";
import Header from "./Header";
import Footer from "./Footer";
import Card from "./Card";
import Btt from "./BackToTop";
import info from "../info";
function Bolt() {
return(
<div>
<Header />
<div>
<h1 className="projHead">Bolt</h1>
<div className="card-img-top"><img src={info.[1].src} alt="" className="banner"></img>
</div>
</div>
<div className="text1">
<h3>Mind Map</h3>
</div>
<div className="card-img-top"><img src={info.[1].pic1} alt="" className="isoimg"></img></div>
<div className="card-img-top"><img src={info.[1].pic2} alt="" className="isoimg"></img></div>
<div className="card-img-top"><img src={info.[1].pic3} alt="" className="isoimg"></img></div>
<div className="card-img-top"><img src={info.[1].pic4} alt="" className="isoimg"></img></div>
<div className="text1">
<h3>Screen Layouts</h3>
</div>
<div className="card-img-top"><img src={info.[1].pic5} alt="" className="isoimg"></img></div>
<div className="text1">
<h3>Mockups</h3>
</div>
<div className="card-img-top"><img src={info.[1].pic6} alt="" className="smallisoimg"></img></div>
<Btt />
<Footer />
</div>
);
}
export default Bolt;
this is the JS file for content
const info = [
{
id: 1,
title: "AR mirror",
about: "Smart Exercise Mirror is an IOT product. It helps the user to have a gym-like experience at their home with the help of AR and image recognition technology. ",
src: "images/AR_Mirror/AR_mirror.png",
tag1: "UX & Product design",
link: "/ARmirror",
targ: "_self",
pic1: "images/AR_Mirror/ar1.jpg",
pic2: "images/AR_Mirror/ar2.png",
pic3: "images/AR_Mirror/ar3.png",
pic4: "images/AR_Mirror/ar4.png",
pic5: "images/AR_Mirror/ar5.gif",
pic6: "images/AR_Mirror/ar6.png",
vid: "images/AR_Mirror/AR_mirror.MOV",
},
{
id: 2,
title: "Bolt",
about: "Bolt is an app for electric bikes which allows user to monitor the bike from remote distance and functions as a control panel.",
src: "images/Bolt/Bolt.jpg",
tag1: "UX design",
link: "/Bolt",
targ: "_self",
pic1: "images/Bolt/bs1.png",
pic2: "images/Bolt/bs2.png",
pic3: "images/Bolt/bs3.png",
pic4: "images/Bolt/bs4.png",
pic5: "images/Bolt/bs5.png",
pic6: "images/Bolt/bs6.gif",
}
];
export default info;
I believe, this syntax (info.[1]) is wrong. That's why you have errors.
You should change it to info[1]. Thats orthodox way of accessing array elements by their indices.
Other than this, you should better use map or foreach iterating over array.
In that case just replace
info.[1].pic1
to
info?.[1]?.pic1
If you doing it static then its fine.
But in future if you are using more data it will be better to use For-loop or Map because it's better way to use array data

How to display button only when a link is provided via another file (React)

I am working on my personal portfolio site with React and Tailwind. I am trying to figure out how to display the "GitHub" button for my project card only when I provide a GitHub link via my data.js file.
I am using a card component and the map method to display a card for each project provided in the data.js. As you can see, I don't provide a GitHub link to the first project, but I do on the second one. How can I make the GitHub button appear for projects I only provide a GitHub link?
I tried to create a function to display the button only when there is an href value provided but that did not work. Any suggestions that can lead me in the right direction are highly appreciated.
GitHub repo: https://github.com/fotinh0/my-portfolio
data.js
export const projects = [
{
title: "PCI Media Website",
subtitle: "Company Website using WordPress",
description:
"Maintained PCI Media's multi-page website as an intern using WordPress with the Divi theme. Increased traffic using SEO techniques and Google Analytics",
skills: "Built with: WordPress, HTML, CSS",
image: "./gif-files/pcimedia.gif",
link: "https://www.pcimedia.org/",
github: ""
},
{
title: "Keeper App",
subtitle: "React Clone of Google Keep",
description:
"Keep track of your notes and your to-do's using the Keeper App. Inspired by the Google Keep application.",
skills: "Built with: React, Material UI",
image: "./gif-files/keeper-app.gif",
link: "https://keeper-app-fc.netlify.app/",
github: "https://github.com/fotinh0/keeper-app"
}, ...
Projects.js
import { projects } from "../data";
export default function Projects() {
return (
<section id="projects" className="...">
<div className="container ...">
{/* additional code here */}
{/* Projects Cards */}
<div className="flex flex-wrap -m-4">
{projects.map((project) => (
<a
href={project.link}
key={project.image}
className="sm:w-1/2 w-100 p-4">
{/* additional code here */}
<div className="project-buttons ...">
<a className="live-site ..." href={project.link} target="_blank"> Live Site</a>
<a className="github ..." href={project.github} target="_blank">GitHub</a>
</div>
</a>
))}
</div>
</div>
</section>
);
}
Use a condition, like this:
{project.github && (
<a className="github ..." href={project.github} target="_blank">GitHub</a>
)}
You might want to check if the variable has a length greater than zero, then you can do:
{project.github.length > 0 && (
<a className="github ..." href={project.github} target="_blank">GitHub</a>
)}
There a few ways to conditionally render elements/components:
You can use the && operator
{project.github &&
<a className="github ..." href={project.github} target="_blank">GitHub</a>
}
or you can use a ternary expression:
{project.github ?
<a className="github ..." href={project.github} target="_blank">GitHub</a>
: null
}
There are additional ways to achieve that, what's important to remember is that they all involve introducing a condition to determine whether the element should render or not.
import { projects } from "../data";
export default function Projects() {
const renderGithubButton = (github) => {
// If github.project is empty then it will show nothing
// But if github.project exists then else will return
if(github.length===0) return ""
else return <a className="github ..." href={project.github} target="_blank">GitHub</a>
}
return (
<section id="projects" className="...">
<div className="container ...">
{/* additional code here */}
{/* Projects Cards */}
<div className="flex flex-wrap -m-4">
{projects.map((project) => (
<a
href={project.link}
key={project.image}
className="sm:w-1/2 w-100 p-4">
{/* additional code here */}
<div className="project-buttons ...">
<a className="live-site ..." href={project.link} target="_blank"> Live Site</a>
//Create a new function to check github exists or not.
// send project.github as argument
{renderGithubButton(project.github)}
</div>
</a>
))}
</div>
</div>
</section>
);
}

Each child in a list should have a unique key prop problem

Good day,
i'm experiencing a slight problem. i want to have productdetails page where all the info is being displayed of the product. You can do that through clicking on the product link. but i'm getting the following err: Each child in a list should have a unique key prop problem
code homepage:
import React from 'react';
import data from '../data'
import { Link } from 'react-router-dom';
function Homescreen (props){
return <ul className="products" >
{ data.products.map(product =>
<li key={product}>
<div className="product-card">
<Link to={'/product/' + product._id}>
<img className="product-image" src={product.image} alt="product"></img>
</Link>
<Link to={'/product/' + product._id}><h1 className="product-name">{product.name}</h1></Link>
<p className="product-price">€{product.price}</p>
<div className="product.rating">Stars ({product.numReviews})</div>
<form method="post">
<button type="submit">Add to cart</button>
</form>
</div>
</li>
)
}
</ul>
}
export default Homescreen;
code productpage:
import React from 'react';
import data from '../data';
import { Link } from 'react-router-dom';
function productScreen (props){
console.log(props.match.params.id)
const product = data.products.find(x=> x._id === props.match.params.id)
return <div>
<h1>product</h1>
<div>
<Link to="/">Back to products</Link>
</div>
<div className="productdetails">
<div className="details-image">
<img src={product.image} alt="product"></img>
</div>
<h1>{product.name}</h1>
<h4>{product.price}</h4>
<span>{product.rating} Stars ({product.numReviews} Reviews)</span>
</div>
</div>
}
export default productScreen;
As stated on the ReactJS Website
A “key” is a special string attribute you need to include when creating lists of elements.
Therefore, a key can not be an object like the way you are using it here and will need to be a String. If your product does not have a unique identifier, then you can choose to use the index of your map method.
When you don’t have stable IDs for rendered items, you may use the item index as a key as a last resort:
// Example from the ReactjS Website
const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs
<li key={index}>
{todo.text}
</li>
);
You should change:
<li key={product}>
To (assuming your id is unique)
<li key={product._id}>
The best way to pick a key is to use a string that uniquely identifies a list item among its siblings, you can check more here

Categories