Unable to render a react component on click of a button - javascript

I have two components: MainContainer and Cart. In MainContainer, I have a button & when clicked it calls a function addToCart with an id argument, which then has to render the Cart component. I am passing that argument as a prop and then extracting the prop value in the Cart component. Wwhen I click on the button, component is not getting rendered. There are no errors as well.
MainContainer.js
import React, { useState } from "react";
import Cart from "./Cart";
import { data } from "./data";
import { Link } from "react-router-dom";
function MainContainer() {
function addToCart(id) {
return (
<div>
<Cart id={id}></Cart>
</div>
);
}
return (
<div className=" grid grid-cols-6">
{data.map((item) => (
<div
key={item.id}
className=" w-52 h-64 m-6 flex flex-col bg-gray-100 shadow-lg border-gray-200 border p-4 items-center justify-center rounded-lg relative"
>
<Link to="/cart">
{" "}
<i
className="fa-solid fa-cart-plus absolute top-3 right-3 cursor-pointer text-lg"
onClick={() => addToCart(item.id)}
></i>
</Link>
<img className=" w-32 h-32" src={item.image} alt="" />
<div className=" bg-gray-300 w-full p-2 rounded-lg mt-2 text-center">
<p className=" font-semibold text-lg"> {item.name}</p>
<p>$ {item.price}</p>
<p>{item.rating}</p>
</div>
</div>
))}
</div>
);
}
export default MainContainer;
Cart.js
import React from "react";
function Cart(props) {
return (
<div>
<h1>hi {props.id} </h1>
</div>
);
}
export default Cart;

addToCart is a callback, it can't return JSX to be rendered. You can store the id in local component state and then conditionally render the Cart component when the id state is populated.
Example:
function MainContainer() {
const [id, setId] = React.useState(); // <-- initially undefined
function addToCart(id) {
setId(id); // <-- defined
}
return (
<div className=" grid grid-cols-6">
{data.map((item) => (
<div
key={item.id}
className="...."
>
<Link to="/cart">
<i
className="...."
onClick={() => addToCart(item.id)}
/>
</Link>
<img className=" w-32 h-32" src={item.image} alt="" />
<div className="....">
<p className=" font-semibold text-lg"> {item.name}</p>
<p>$ {item.price}</p>
<p>{item.rating}</p>
</div>
</div>
))}
{id && (
<div>
<Cart id={id} /> {/* render Cart if id defined */}
</div>
)}
</div>
);
}

Related

im trying to only show the description of the button i press

when i click on the description button, all the mapped containers are showing their descriptions, but i only want the one thats pressed to show its description. so how can i make it so that the container that is pressed will show its id's description?
`import { useState } from "react";
export default function ServiciosCard({ profile }) {
const [normal, setNormal] = useState(true);
const [showDescripcion, setShowDescripcion] = useState(false);
const showDescripcionChangeHandler = () => {
setShowDescripcion(true);
setNormal(false);
};
return (
<>
<div
className=" space-y-4 mt-3 md:mt-0 h-[450px] md:h-[550px] overflow-y-auto
md:scrollbar scrollbar-track-[#d0e7d5] scrollbar-thumb-[#ef8eb2]
text-center "
>
{profile.servicios.map((servicio) => (
<>
{normal && (
<div
key={servicio._id}
className="bg-[#f7ede2] rounded-md w-[300px] h-[75px] "
>
<div>{servicio.unServicio}</div>
<div>1 Hr {servicio.costo}</div>
<div className=" space-x-4">
<button className="text-[#f77f00] hover:headerButton">
Reserva ahora
</button>
<button
onClick={showDescripcionChangeHandler(servicio._id)}
className="text-[#f77f00] hover:headerButton"
>
Descripcion
</button>
</div>
</div>
)}
{showDescripcion && (
<div
key={servicio._id}
className="bg-[#f7ede2] rounded-md w-[300px] h-[75px] "
>
{servicio.description}
</div>
)}
</>
))}
</div>
</>
);
}`
showDescription will show description for all item
you can create a new component Like below an pass srvicio to it.
import { useState } from "react";
export default function ServiciosCard({ profile }) {
return (
<>
<div
className=" space-y-4 mt-3 md:mt-0 h-[450px] md:h-[550px] overflow-y-auto
md:scrollbar scrollbar-track-[#d0e7d5] scrollbar-thumb-[#ef8eb2]
text-center "
>
{profile.servicios.map((servicio) => (
<ServicIo servicio={servicio} />
))}
</div>
</>
);
}
function ServicIo({servicio}){
const [normal, setNormal] = useState(true);
const [showDescripcion, setShowDescripcion] = useState(false);
const showDescripcionChangeHandler = () => {
setShowDescripcion(true);
setNormal(false);
};
return (<>
{normal && (
<div
key={servicio._id}
className="bg-[#f7ede2] rounded-md w-[300px] h-[75px] "
>
<div>{servicio.unServicio}</div>
<div>1 Hr {servicio.costo}</div>
<div className=" space-x-4">
<button className="text-[#f77f00] hover:headerButton">
Reserva ahora
</button>
<button
onClick={showDescripcionChangeHandler(servicio._id)}
className="text-[#f77f00] hover:headerButton"
>
Descripcion
</button>
</div>
</div>
)}
{showDescripcion && (
<div
key={servicio._id}
className="bg-[#f7ede2] rounded-md w-[300px] h-[75px] "
>
{servicio.description}
</div>
)}
</>)
}
in this code showDescription do each item that selected by user.

TailwindCSS styling applies to one React Component list but not the other

Hello I have two cards but one of them is not applying it's TailwindCSS stuff to the divs at all. I hope it's just some stupid error because I'm kind of scratching my head.
Is the relevant incorrect code:
Where it's being rendered in the index page:
Dashboard.tsx:
<div className="flex flex-col border border-red-700">
{orders.map(
({ id, managerId, invoiceNumber, companyName, contact, partNumbers, partNames, quote, locationOnServer, reportType, createdAt }) => {
return (
<WorkOrderCard id={id} managerId={managerId} invoiceNumber={invoiceNumber} companyName={companyName} contact={contact} partNumbers={partNumbers} partNames={partNames} quote={quote} locationOnServer={locationOnServer} reportType={reportType} createdAt={createdAt} timesheet={[]} />
)
}
)}
And here is the component definition WorkOrderCard.tsx:
export default function WorkOrderCard(props) {
const { id, managerId, invoiceNumber, companyName, contact, partNumbers, partNames, quote, locationOnServer, reportType, createdAt, timesheet} = props;
const [manager, setManager] = React.useState<string>("");
useEffect(() => {
if (manager !== undefined) {
const res = fetch("/api/users/get/" + managerId, {
method: 'GET',
}).then((res) => {
if (res.ok) {
res.json().then((manager) => {
setManager(manager.name);
})
} else {
console.log("There was an error fetching the ticket");
// setErrorMessage(res.statusText)
}
})
}
}, [])
return (
/* Trying to draw an outline around the div but It doesn't appear */
<div className="flex outline outline-red-600">
<div className='flex flex-col'>
<div className="flex flex-row">
<div className="flex">Invoice #{invoiceNumber}</div>
<div className="flex">{companyName}</div>
</div>
<div className="card-body">
<div className="card-text">
<strong>Contact:</strong> {contact || 'N/A'}
</div>
<div className="card-text">
<strong>Part Numbers:</strong>{' '}
{partNumbers.length > 0 ? partNumbers.join(', ') : 'N/A'}
</div>
<div className="card-text">
<strong>Part Names:</strong>{' '}
{partNames.length > 0 ? partNames.join(', ') : 'N/A'}
</div>
<div className="card-text">
<strong>Quote:</strong> ${quote}
</div>
<div className="card-text">
<strong>Location on Server:</strong> {locationOnServer}
</div>
<div className="card-text">
<strong>Report Type:</strong> {reportType}
</div>
<div className="card-text">
<strong>Created At:</strong> {createdAt.toString()}
</div>
<div className="card-text">
</div>
<div className="card-text">
<strong>Manager:</strong> {manager}
</div>
{timesheet.length > 0 && (
<div className="card-text">
<strong>Time Sheet:</strong>
<ul>
{timesheet.map((time) => (
<li key={time.id}>
{new Date(time.date).toLocaleString()} - {new Date(time.date).setHours(new Date(time.date).getHours() + time.hours).toLocaleString()}
</li>
))}
</ul>
</div>
)}
</div>
</div>
</div>
);
};
The working code is called like this Dashboard.tsx:
<div className="flex flex-col justify-evenly border border-red-700">
{tickets.map(
({ id, creator, broken_item, issue_desc, loc, prio, active, creatorName, createdAt }) => {
return (
<TicketGUI className="m-3" id={id} creator={creator} broken_item={broken_item} issue_desc={issue_desc} loc={loc} prio={prio} active={active} name={creatorName} createdAt={createdAt} />
)
}
)}
<div className="flex justify-between m-2">
<button onClick={() => {
ticketPageSelect(currentSession.user.id, tickets[0].id, setTickets, true, pageSize)
}} className="justify-end px-4 py-2 text-sm text-blue-100 bg-blue-500 rounded shadow">
Prev
</button>
<button onClick={() => {
ticketPageSelect(currentSession.user.id, tickets[tickets.length - 1].id, setTickets, false, pageSize)
}} className="justify-end px-4 py-2 text-sm text-blue-100 bg-blue-500 rounded shadow">
Next
</button>
</div>
</div>
And here is the working component TicketGUI.tsx:
export default function TicketGUI(props){
const handlePress = async (e) => {
Router.push('/tickets/'+props.id)
}
return (
<div className="flex flex-col rounded-lg shadow-lg p-2 m-3 outline outline-blue-300">
<div className="flex ">
<img
className="object-cover h-12"
src={props.active ? "/inprocess.png" : "/fixed.png"}
alt="image"
/>
<h1 className=" ml-2 text-xl font-semibold tracking-tight text-blue-600 whitespace-nowrap">
{props.broken_item} - TicketID: {props.id}
</h1>
</div>
<div className="p-4">
<p className="mb-2 leading-normal">
{props.issue_desc}
</p>
<div className="flex w-full">
<button onClick={handlePress} className="px-4 py-2 text-sm text-blue-100 bg-blue-500 rounded shadow">
View Details
</button>
<p className="p-2">
{format(new Date(props.createdAt),'MM/dd/yyyy')}
</p>
</div>
</div>
</div>
);
}
Any help would be appreciated Chat-GPT suggested this but no dice and I factored out className from props:
It looks like the problem is that the className prop is being passed
to the component but it is not being used to apply classes to the
elements within the component. In the code you posted, the className
prop is only being used to specify the component's own class, but it
is not being used to apply classes to the elements within the
component.
To fix this, you can either use the className prop to specify the
classes for each element within the component, or you can use the
className prop to specify the classes for the component itself and
then use the class prop to specify the classes for the elements within
the component.
For example, you could change this line:
<div className={className}>
to this:
<div className={className}>
<div className='flex flex-col'>
<div className="flex flex-row">
...
</div>
<div className="card-body">
...
</div>
</div>
</div>

React Route not adding forward slash with path="/post/:slug"

For some reason when I click on one of the posts in the collection of posts section to view the info on one single post, my code is not adding a forward slash / in the URL like so : http://localhost:3000/postyou-just-could-not-have where the URL I need is http://localhost:3000/post/you-just-could-not-have.
Is there a way to add a / to the URL or figure out why it is not being generated?
App.js with Route <Route path="/post/:slug" element={<SinglePost />} /> in question :
import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Home from './components/Home';
import About from './components/About';
import SinglePost from './components/SinglePost';
import Post from './components/Post';
import Project from './components/Project';
import NavBar from './components/NavBar';
function App() {
return (
<Router>
<NavBar />
<Routes>
<Route path="/" element={<Home />} exact />
<Route path="/about" element={<About />} />
<Route path="/post/:slug" element={<SinglePost />} />
<Route path="/post" element={<Post />} />
<Route path="/project" element={<Project />} />
</Routes>
</Router>
);
}
export default App;
SinglePost.js component attempting to build URL from slug value :
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import sanityClient from '../client';
import BlockContent from '#sanity/block-content-to-react';
import imageUrlBuilder from '#sanity/image-url';
const builder = imageUrlBuilder(sanityClient);
function urlFor(source) {
return builder.image(source);
}
export default function SinglePage() {
const [singlePost, setSinglePost] = useState(null);
const { slug } = useParams();
useEffect(() => {
sanityClient
.fetch(
`*[slug.current == "${slug}"]{
title,
_id,
slug,
mainImage{
asset->{
_id,
url
}
},
body,
"name": author->name,
"authorImage": author->image
}`
)
.then((data) => setSinglePost(data[0]))
.catch(console.error);
}, [slug]);
if (!singlePost) {
return <div>Loading...</div>;
}
return (
<main className="bg-gray-200 min-h-screen p-12">
<article className="container shadow-lg mx-auto bg-green-100 rounded-lg">
<header className="relative">
<div className="absolute h-full w-full flex items-center justify-center p-8">
<div className="bg-white bg-opacity-75 rounded p-12">
<h1 className="cursive text-3xl lg:text-6xl mb-4">
{singlePost.title}
</h1>
<div className="flex justify-center text-gray-800">
<img
src={urlFor(singlePost.authorImage).url()}
alt="bob"
className="w-10 h-10 rouded-full"
/>
<p className="cursive flex items-center pl-2 text-2xl">
{singlePost.name}
</p>
</div>
</div>
</div>
<img
src={singlePost.mainImage.asset.url}
alt="gary"
className="w-full object-cover rounded-t"
style={{ height: '400px' }}
/>
</header>
<div className="px-16 lg:px-48 py-12 lg:py-20 prose lg:prose-xl max-w-full">
<BlockContent
blocks={singlePost.body}
projectId="notReally"
dataset="production"
/>
</div>
</article>
</main>
);
}
Adding Post.js :
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import sanityClient from '../client';
export default function Post() {
const [postData, setPost] = useState(null);
useEffect(() => {
sanityClient
.fetch(
`*[_type == "post"]{
title,
slug,
mainImage{
asset->{
_id,
url
},
alt
}
}`
)
.then((data) => setPost(data))
.catch(console.error);
}, []);
//anything wrapped in Link makes it clickable
return (
<main className="bg-green-100 min-h-screen p-12">
<section className="container mx-auto">
<h1 className="text-5xl flex justify-center cursive">Blog Post Page</h1>
<h2 className="text-lg text=gray-600 flex justify-center mb-12">
Welcome Doggies
</h2>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
{postData &&
postData.map((post, index) => (
<article>
<Link to={'/post' + post.slug.current} key={post.slug.current}>
<span
className="block h-64 relative rounded shadow leading-snug bg-white border-l-8 border-green-400"
key={index}
>
<img
src={post.mainImage.asset.url}
alt="photo"
className="w-full h-full rounded-r object-cover absolute"
/>
<span className="block relative h-full flex justify-end items-end pr-4 pb-4">
<h3 className="text-gray-800 text-lg font-blog px-3 py-4 bg-red-700 text-red-100 bg-opacity-75 rounded">
{post.title}
</h3>
</span>
</span>
</Link>
</article>
))}
</div>
</section>
</main>
);
}
Links are relative to the route hierarchy by default, unless given a value begin with /.
More about Link
In <Post />, try one of the following:
<Link to={post.slug.current} key={post.slug.current}>
...
/Link>
Or:
<Link to={'/post/' + post.slug.current} key={post.slug.current}>
...
/Link>
These will hopefully generate the right path as /post/:slug.

Can anyone tell me problem with this code? Navbar is not getting displayed

In console this error is getting displayed:
enter image description here
Everything is fine but navbar is not getting displayed with the error above.
Here is my App.js file
import Navbar from './components/Navbar';
import './App.css';
import AddEmployee from './components/AddEmployee';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import EmployeeList from './components/EmployeeList';
function App() {
return (
<>
<BrowserRouter>
<Navbar/>
<Routes>
<Route index element={<EmployeeList/>}/>
<Route path="/" element={<EmployeeList/>}></Route>
<Route path ="/employeeList" element={<EmployeeList/>}></Route>
<Route path ="/addEmployee" element={<AddEmployee/>}></Route>
</Routes>
</BrowserRouter>
</>
);
}
export default App;
Navbar.js
import React from 'react'
const Navbar = () => {
return (
<div className="bg-gray-800">
<div className='h-16 px-8 flex items-center'>
<p className='text-white font-bold'>Employee Management System </p>
</div>
</div>
)
}
export default Navbar;
AddEmployee.js
import React, {useState} from 'react'
import employeeService from '../services/employeeService';
const AddEmployee = () => {
const [employee, setEmployee] = useState({
id: "",
firstName: "",
lastName: "",
emailId: "",
})
const handleChange = (e) => {
const value = e.target.value;
setEmployee({...employee,[e.target.name] : value});
}
const saveEmployee = e => {
e.preventDefault();
employeeService.saveEmployee(employee).then((response) =>{
console.log(response);
}).catch((err) => {
console.log(err);
})
}
return (
<div className="flex max-w-2xl mx-auto shadow border-b">
<div className="px-8 py-8">
<div className="font-thin text-2xl tracking-wider">
<h1>Add New Employee</h1>
</div>
<div className="justify-center items-center h-14 w-full my-4">
<label className="block text-gray-600 text-sm font-normal" >First Name</label>
<input className="h-10 w-96 border mt-2 px-2 py-2"
type="text"
value = {employee.firstName}
onChange = {(e) => handleChange(e)}
name="firstName"></input>
</div>
<div className="justify-center items-center h-14 w-full my-4">
<label className="block text-gray-600 text-sm font-normal" >Last Name</label>
<input className="h-10 w-96 border mt-2 px-2 py-2"
type="text"
value = {employee.lastName}
onChange = {(e) => handleChange(e)}
name="lastName"></input>
</div>
<div className="justify-center items-center h-14 w-full my-4">
<label className="block text-gray-600 text-sm font-normal" >E-Mail</label>
<input className="h-10 w-96 border mt-2 px-2 py-2"
type="email"
value = {employee.emailId}
onChange = {(e) => handleChange(e)}
name="emailId"></input>
</div>
<div className="justify-center items-center h-14 w-full my-4 space-x-4">
<button
className="rounded text-white font-semibold bg-red-600 px-6 hover:bg-green-500 py-2"
onClick={saveEmployee}>
Save
</button>
<button
className="rounded text-white font-semibold bg-orange-600 px-6 hover:bg-green-500 py-2"
>
Clear
</button>
</div>
</div>
</div>
)
}
export default AddEmployee;
It doesnot contain much but just check if there is any error
EmployeeList.js
import React from 'react'
const EmployeeList = () => {
return (
<div>EmployeeList</div>
)
}
export default EmployeeList;
when i am using addEmployee route navbar is working properly but this error persists even then.
Be sure that BrowserRouter is the first element in the Return
<BrowserRouter>
<>
<Navbar/>
<Routes>
....
</>
</BrowserRouter>

Run or execute script after page is loaded with react helmet, react gatsbyjs

i have a blog post page that load content via graphql, in the content are scripts tag of charts.
the problem is that when using it does not load the scripts. Only load the scripts if you refresh the browser.
So i added the scripts to helmet after data loaded but they dont run/load .
Is there a way to "refresh" the dom?
import React, { useEffect,useState, Suspense } from "react"
import { Link, graphql } from "gatsby"
import Img from "gatsby-image"
import Layout from "../components/layout"
import EmbedContainer from "react-oembed-container"
import SEO from "../components/seo"
import { Helmet } from "react-helmet"
const PostContentComponent = React.lazy(() => import('../components/PostContentComponent'));
const BlogPost = ({ data }) => {
const [scripts,setScripts] = useState([])
function getScripts () {
// get all script tags from content
const re = /<script\b[^>]*>[\s\S]*?<\/script\b[^>]*>/g
const results = setScripts(data.strapiPost.content.match(re))
return results
}
console.log('scripts', scripts)
useEffect(() => {
getScripts()
// window.instgrm.Embeds.process()
// window.twttr.widgets.load()
}, [data])
return (
<>
<Layout>
<Helmet>
{scripts ? scripts.map((script)=> {
return script
}): null}
</Helmet>
<SEO title={data.strapiPost.title}/>
<section className="posts-container mx-auto all-blog-content my-5 sm:my-20 px-5">
<h3 className="text-1xl sm:text-3xl font-black mb-3">
{data.strapiPost.title}
</h3>
<div className="autor flex flex-wrap items-start">
<div className="autores flex ">
<div className="autorInfo flex items-start">
<h2 className="text-sm tracking-tighter text-gray-900">
By{" "}
{data.strapiPost.users_permissions_users.length === 1 ? (
<>
<Link className="hover:text-black transition duration-300 ease-in-out text-xs mr-1">
{data.strapiPost.users_permissions_users[0].username}
</Link>{" "}
</>
) : data.strapiPost.users_permissions_users.length === 2 ? (
data.strapiPost.users_permissions_users.map((x, index) => (
<>
<Link
className="hover:text-black transition duration-300 ease-in-out text-xs mr-1"
>
{x.name} {x.lastname}{" "}
{index <
data.strapiPost.users_permissions_users.length - 1
? " &"
: ""}
</Link>
</>
))
) : null}
</h2>
</div>
</div>
{/* LOAD CATEGORIES */}
<div className="md:ml-5">
<ul className="flex flex-nowrap relative ">
{data.strapiPost.categories.map(cat => {
return (
<Link
key={cat.name}
className={`bg-gray-200 py-1 px-2 mr-1 rounded-lg text-black text-xs flex-grow `}
>
{cat.name}
</Link>
)
})}
</ul>
</div>
</div>
<span className="text-gray-600 mr-3 text-xs">
Updated at {new Date(data.strapiPost.updated_at).toDateString()}
</span>
<div className="posts-content py-10">
<Img
alt={data.strapiPost.title}
key={data.strapiPost.featured_image.childImageSharp.fluid.src}
imgStyle={{ objectFit: "contain" }}
fluid={data.strapiPost.featured_image.childImageSharp.fluid}
className="mb-10"
/>
<EmbedContainer markup={data.strapiPost.content}>
<div
dangerouslySetInnerHTML={{ __html: unescape(data.strapiPost.content) }}
/>
</EmbedContainer>
</div>
{/* end of all posts */}
{/* AUTHOR CARD */}
<h3 className="text-2xl font-black text-center my-10">
Read More posts by this Author{" "}
</h3>
</section>
<section className="posts-container mx-auto">
<div
className={`grid grid-cols-1 sm:grid-cols-${data.strapiPost.users_permissions_users.length} md:grid-cols-${data.strapiPost.users_permissions_users.length} xl:grid-cols-${data.strapiPost.users_permissions_users.length} gap-4 my-5`}
>
{data.strapiPost.users_permissions_users.map((user, index) => {
return (
<div
key={index}
className="bg-purple-50 flex flex-col items-center justify-center bg-white p-4 shadow rounded-lg"
>
<div className="inline-flex shadow-lg border border-gray-200 rounded-full overflow-hidden h-40 w-40">
{/* <img
src="https://platformable.com/content/images/2020/03/headshot-profile.png"
alt=""
className="h-full w-full my-0"
/> */}
<Img
alt={data.strapiPost.title}
key={index}
fluid={user.image.childImageSharp.fluid}
className="h-full w-full my-0"
/>
</div>
<h2 className="mt-4 font-bold text-xl">
{user.name} {user.lastname}
</h2>
<h6 className="mt-2 text-sm font-medium">{user.position}</h6>
<p className="text-xs text-gray-500 text-center mt-3">
{user.bio}
</p>
</div>
)
})}
</div>
</section>
</Layout>
</>
)
}
export default BlogPost
export const query = graphql`
query MyPost($slug: String!) {
strapiPost(slug: { eq: $slug }) {
categories {
name
}
content
id
title
users_permissions_users {
id
name
lastname
username
image {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
position
}
updated_at
featured_image {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
}
}
`
Have you tried something like this:
<Helmet>
{scripts && scripts.map((script)=> <script>{script}</script>)}
</Helmet>
Based on: https://github.com/gatsbyjs/gatsby/issues/6299#issuecomment-402793089
Alternatively, you can use the custom hook approach (useScript).

Categories