How to add hyperlink to array format in react.js? - javascript

I want to add a hyperlink by put that url info to data array.
But the anchor tag with href does not work as I thought.
Should I use react-router-dom's Link tag? Or would there be any clue to add hyperlink when I add {link} on Goods.js?
#1 Shop.js
export const Shop = () => {
return (
<div className="shop">
<div className="shop-title">
<h1>Anime Biased Shop</h1>
</div>
<div className="items">
{ItemsList.map((item) => (
<Goods shopItemProps={item} />
))}
</div>
</div>
);
};
#2 Goods.js
import React, { useState } from "react";
export const Goods = (props) => {
const { id, name, price, image, link } = props.shopItemProps;
const [count, setCount] = useState(0);
return (
<>
<div className="goods">
<div>{id}</div>
<img src={image} alt="thumbnail_image" />
<div className="goods-name">{name}</div>
<div className="goods-price">${price}</div>
<a href={link} />
<div className="cart-button">
<button onClick={() => setCount(count - 1)}>-</button>
{count}
<button onClick={() => setCount(count + 1)}>+</button>
</div>
</div>
</>
);
};
#3 ItemsList.js (the data array file I mentioned)
export const ItemsList = [
{
id: 1,
name: "VA-11 Hall-A: Cyberpunk Bartender Action",
price: 110000,
image: cover1,
link: "https://store.steampowered.com/app/447530/VA11_HallA_Cyberpunk_Bartender_Action/?l=koreana",
},

There are two options.
1. External links or redirect with page refresh
If it is external link, to other website you should use a. This looks nice
<a href={link} />
but can be not visible, because you do not have any content in this link. You can change it to:
<a href={link}><button>Click me</button></a>
2. Internal links without page reload
If it is internal link, you should remove domain, eg by replace function and use Link if you using next
<Link href="/about">About Us</Link>
https://nextjs.org/docs/api-reference/next/link
or Redirect if you using react-router-dom
<Redirect to='/profile' />
https://www.telerik.com/blogs/programmatically-navigate-with-react-router
In both cases you should add something inside of this element or add classes that make id visible.

You Can Test click me
or React Router Dom like this :
const data = [
{
name: "john",
profile: "/profile",
linkTo: "/user/john",
},
];
{
data.map((item, index) => {
return (
<Link to={item.linkTo}>
<h1>name:{item.name}</h1>
<Link to={item.profile}>
<h5>editProfile</h5>
</Link>
</Link>
);
});
}

Related

Easy way to display internal and external links in gatsby

I am making my website portfolio and I have created a Navbar component with links to home page, project page and blog page. The Home page and blog page are internal links while the projects link is an external link.
Now the way I have this setup is like this:
import * as React from 'react';
import { Link, useStaticQuery, graphql } from 'gatsby';
import Icon from '../images/icon.svg';
const Navbar = ({pageTitle}) => {
const data = useStaticQuery(graphql`
query {
site {
siteMetadata {
title
}
}
}
`);
const menu = [
{ title: 'HOME', path:'/' },
{ title: 'PRØJECTS', path: 'https://github.com/chukkyiii?tab=repositories' },
{ title: 'BLØG', path: '/blog' }
]
return (
<main>
<title>
{pageTitle} | {data.site.siteMetadata.title}
</title>
<div>
<div className="mx-auto mb-9 flex items-center justify-between max-w-2xl ">
<Icon className="w-12 h-12 p-1 rounded-full ring-2 ring-gray-300 dark:ring-gray-500" />
<nav>
<ul className="flex">
{menu.map((item) => (
<li key={item.title}>
<Link to={item.path} className="pl-8 hover:text-amber-500">
{item.title}
</Link>
</li>
))}
</ul>
</nav>
</div>
</div>
</main>
);
}
export default Navbar;
So I don't have to repeat the same line of code again, I just used a Link which works but it gives me a warning, is there a different way I can do this without the warning?
the warning it gives:
react_devtools_backend.js:4026 External link https://github.com/chukkyiii?tab=repositories was detected in a Link component. Use the Link component only for internal links. See: https://gatsby.dev/internal-links
...
You can easily customize your menu array to display a new property to base your loop on:
const menu = [
{ title: 'HOME', path:'/', isInternal: true },
{ title: 'PRØJECTS', path: 'https://github.com/chukkyiii?tab=repositories', isInternal: false },
{ title: 'BLØG', path: '/blog', true }
]
Then:
{
menu.map((item) => {
if (item.isInternal) {
return (
<li key={item.title}>
<Link to={item.path} className="pl-8 hover:text-amber-500">
{item.title}
</Link>
</li>
);
}
return (
<li key={item.title}>
<a href={item.path} target="_blank">
{item.title}
</a>
<li key={item.title}>
);
});
}
You can even do a ternary condition inside the return to take advantage of the <li> wrapper:
{
menu.map((item) => (
<li key={item.title}>
{item.isInternal ? (
<Link to={item.path} className="pl-8 hover:text-amber-500">
{item.title}
</Link>
) : (
<a href={item.path} target="_blank">
{item.title}
</a>
)}
</li>
));
}
Link component is intended to use only for internal navigation, somethign what happens in the scope of your application and React/Gatsby can be aware of. If the link points to any external source (like GitHub in this case), you need to use the standard anchor (which in fact is what it renders the Link component).
The same approach of adding the isInternal attribute (which personally I find it more succinct) can be done in the same way using a regular expression or similar, just checking how the path is.

HIde load more button when all items are from array displayed in react

This should be easy but of course I can't figure it out :)
Basically I've implemented a "load more" button when there are more items to display from array but when it reaches the end, I'd like to hide it. The code below doesn't work and I have a feeling it's because it need to check the index of the array and if it's at the end, then hide the button but I am unsure of how to go about the syntax. Thanks
import { useState } from 'react'
import releases from "../data/releases.json";
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import '../main.css'
const Release = () => {
// get first 12 items in array & load next 12 with "see more button"
const STEP = 12;
const [items, setItems] = useState(releases.slice(0, STEP));
const loadMore = () => {
setItems([...items, ...releases.slice(items.length, items.length + STEP)]);
};
return (
<Wrapper>
<div className="release fadein">
{items.map((item, i) => (
<div className="item" key={i}>
<Link to={`/release/${item.id}`}>
<img src={item.imageURL} alt={item.artist} />
</Link>
</div>
))}
{/* code that isn't working here */}
{items ? <button onClick={loadMore} className="btn" > show more </button> : <button className="btn hidden" ></button>}
</div>
</Wrapper >
)
}
when the items are less than 12 the button will not be displayed
{items%12 ===0 ? <button onClick={loadMore} className="btn" > show more </button> : nul}

how do i update my app sidebar dynamicaly

function TinderCards() {
const [people, setPeople] = useState([
{
name: "Model Baby",
url:"https://www.themodelskit.co.uk/wp-
content/uploads/2021/10/shutterstock_1431963185.jpg",
age:22
},
{
name: "Seema Jaswal",
url:"https://static.standard.co.uk/2021/06/14/16/euro_2020_live_seema_jaswal_01-1.jpg?
width=968&auto=webp&quality=50&crop=968%3A645%2Csmart",
age:32
},
{
name: 'Baby',
url: '../assets/IMG_20210811_105110_849.webp'
age: 34
}
]);
I am pullin data from a datebase that is like the data i created above for illustration purposes
useEffect(() => {
const allPeople = query(collection(db, "people"))
onSnapshot(allPeople, (snapshot) => (
setPeople(snapshot.docs.map((doc) => doc.data()))
))
return () => {
second
}
}, [])
I am updating the app with the information from the database
return (
<div>
<div className='tinderCards__cardContainer'>
{people.map((person) => (
<TinderCard className="swipe" key={person.name} preventSwipe={["up, down"]} onClick=
{() => {setPer(person.name)}} >
<div className='card' style={{ backgroundImage: `url(${person.url})`}}>
<h3>{person.name}</h3>
</div>
</TinderCard>
))}
</div>
</div>
)
}
export default TinderCards
but how do i update my sidebar with this infomatiom and have the name and other infomation change, eachtime the name changes in the main app
function RightSidebar() {
return (
<div className='rightSidebar'>
<div className='rightSidebar__contents'>
<h1>About</h1>
<Card className='rightSidebar__card'>
<div className='card__nameContents'>
<CardHeader className='card__nameAge' title = {name} subheader = {age}
avatar = {<VerifiedIcon className='activeIcon verified' />} />
<CardHeader className='card__active' title = "active" avatar=
{<FiberManualRecordIcon className='activeIcon' />} />
</div>
The app is quite small do i really need redux or is there a way to track the changes with useState hook?
How far is the common parent of RightSidebar and TinderCards?
If one level up or not too far, store the people data as state of the common parent, pass the data to right sidebar and a function to update the sidebar to TinderCards.
If common parent is far, you can use the React Context API (or the useContext hook).
You don't need redux for this

Routing not working using Gatsby - reach-router

I'm trying to render a blog as a card then open it up as a page , but its proving to be difficult using Gatsby. I did the exact same thing fine with react using React router but it doesn't seem to be working with Gatsby. I know I can use GraphQL but surely I can do the same thing using REST. Im using Contentful btw
I switched to reach router as suggested in another post but that doesnt work.
I kept getting this error when I used react-router-dom:
Invariant failed: You should not use <Link> outside a <Router>
Fetching Blog contents
function Blog() {
const [blogs, setBlogs] = useState([])
const [image, setImage] = useState()
const [selectedBlog, setSelectedBlog] = useState(blogs)
useEffect(() => {
fetch("http://cdn.contentful.com...")
.then(response => response.json())
.then(data =>
setBlogs(data.items)
)
}, [])
console.log(blogs)
return (
<>
<div className="card-flex" >
{selectedBlog !== null ? blogs.map((blog =>
<Card title={blog.fields.title} date={blog.fields.date} introduction={blog.fields.introduction} mainBody1={blog.fields.mainBody1} mainBody2={blog.fields.mainBody2} setSelectedBlog={selectedBlog}
/>
)):
<Article title={blogs.find(d => d.fields.title === selectedBlog)} />
}
</div>
</>
)
}
export default Blog
Blog Card
function Card(props) {
console.log(props)
return (
<div class="container">
<div class="card">
<div class="card-header">
<img style={{backgroundImage: "url('https://i.pinimg.com/564x/7f/bb/97/7fbb9793b574c32f5d28cae0ea5c557f.jpg')"}}/>
</div>
<div class="card-body">
<span class="tag tag-teal">{props.tags}</span>
<h4>{props.title}</h4>
<p style={{fontSize:"17px", paddingTop:"10px"}} >{props.introduction}</p>
<div class="card-user">
<Link
to={{
pathname: '/article',
state: {
title: props.title,
introduction: props.introduction
}
}}
>
<button>read more</button>
</Link>
<div class="user-info">
<h5 >{ props.date}</h5>
</div>
</div>
</div>
</div>
</div>
)
}
export default Card
**Article **
import React from 'react'
import './Article.css'
import { useLocation } from "#reach/router"
function Article(props) {
// useLocation to access the route state from Blog.js
const { state = {} } = useLocation();
console.log(state)
return (
<div className="main">
<h1 className="title">{state.title}</h1>
<p className="intro">{state.introduction}</p>
<p className="main1">{state.mainBody1}</p>
<p className="main2">{state.mainBody2}</p>
</div>
)
}
export default Article
I think you are mixing stuff. Gatsby extends from #reach/router so you don't need to use its notation. Your Link should look like:
<Link
to={`/article`}
state={{
title: props.title,
introduction: props.introduction
}}
>
Assuming your /article page exists under /pages folder.

Having a problem loading in data to child component in react

I am building a gallery where you click on the image and it will load in a separate component using props, this image is a URL, taken from a hard-coded array, where the src is loaded as a background image via CSS. My challenge is connecting the data to that component. I have tried connecting the data from parent to child with callbacks, but no luck. I think what I am trying to do is connect components sideways, and I don't want to use redux, as I am not familiar.
Note: I am aware you can just load the image in GalleryContainer.js using window.location.href = "props.src/", however, I want the image to load in the Image component that will act as a container to hold the image giving the user other options such as downloading the image, etc...
Note: I have tried importing the Image component in Gallery.js and rendering it like so: <Image src={props.src} id={props.id}/>, and I find the data connects just fine, but this does not help keep the component separate.
What I have already :
I have a route in app.js that allows me to go to the image route path just fine it’s loading in the url from props.src in the image component that is my challenge
UPDATE: SOLVED Click here to see the solution!
Here is the code:
GalleryList.js
import Gallery from "./Gallery";
import Header from "./UI/Header";
import Footer from "./UI/Footer";
import styles from "./Gallery.module.css";
const DUMMY_IMAGES = [
{
id: "img1",
src: "https://photos.smugmug.com/photos/i-vbN8fNz/1/X3/i-vbN8fNz-X3.jpg",
},
{
id: "img2",
src: "https://photos.smugmug.com/photos/i-fSkvQJS/1/X3/i-fSkvQJS-X3.jpg",
},
{
id: "img3",
src: "https://photos.smugmug.com/photos/i-pS99jb4/0/X3/i-pS99jb4-X3.jpg",
},
];
const GalleryList = () => {
const imagesList = DUMMY_IMAGES.map((image) => (
<Gallery id={image.id} key={image.id} src={image.src} />
));
return (
<>
<Header />
<ul className={styles.wrapper}>
<li className={styles.list}>{imagesList}</li>
</ul>
Home
<Footer />
</>
);
};
export default GalleryList;
Gallery.js
import GalleryConatiner from "./UI/GalleryContainer";
import styles from "./Gallery.module.css";
const Gallery = (props) => {
return (
<>
<div className={styles["gal-warp"]}>
<GalleryConatiner id={props.id} key={props.id} src={props.src} />
</div>
</>
);
};
export default Gallery;
GalleryContainer.js
import styles from "../Gallery.module.css";
const GalleryConatiner = (props) => {
const selectedImg = () => {
if (props.id) {
// window.location.href = `image/${props.src}`;
window.location.href = "image/"
}
};
return (
<ul>
<li className={styles["gallery-list"]}>
<div
onClick={selectedImg}
className={styles["div-gallery"]}
style={{
backgroundImage: `url(${props.src}`,
height: 250,
backgroundSize: "cover",
}}
></div>
</li>
</ul>
);
};
export default GalleryConatiner;
Image.js
import styles from "./Image.module.css";
const Image = (props) => {
return (
<section>
<h1 className={styles["h1-wrapper"]}>Image:{props.id}</h1>
<div className={styles.wrapper}>
<div
className={styles["image-container"]}
style={{
backgroundImage: `url(${props.src}`,
}}
></div>
</div>
</section>
);
};
export default Image;
You should be able to use the router Link to pass data via "state" on the to property.
From React Router's documentation:
<Link
to={{
pathname: "/images",
state: { imgUrl: props.src }
}}
/>

Categories

Resources