Javascript variables in css are not working - javascript

In this code i am passing both imageurl and size which are javascript variables but i am using in css.
css is not considering both. How to resolve this issue ??
const MenuItem = ({title, imageUrl, size}) => {
return(
<div className="${size} menu-item">
<div className="background-image" style={{backgroundImage: "url(${imageUrl})"}} />
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
);
}

This should work:
const MenuItem = ({title, imageUrl, size}) => {
return(
<div className={`${size} menu-item`}>
<div className="background-image" style={{backgroundImage: "url(${imageUrl})"}} />
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
);
}

To use variables inside a string like this, you need to use the following syntax:
className={`${size} menu-item`}

You should wrap them in back-ticks (``):
const MenuItem = ({title, imageUrl, size}) => {
return(
<div className=`${size} menu-item`>
<div className="background-image" style={{backgroundImage: `${url(${imageUrl})}`}} />
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
);
}

Related

How do I use Toggle method in Reactjs ? I have added sandbox link at the bottom

In this code, I want to toggle active class to icons div, I watched some youtube videos and they showed this method which is not what I want, this method does not add activeclass to a particular div it adds active class to every div that has icons class. I want whenever someone click onto the div active class should be added into it and when clicked again that class should get removed.
export default function Site() {
const [notActive, setActive] = useState(false);
const switchActive = () => {
notActive ? setActive(false) : setActive(true);
};
return (
<div id="container">
<nav id="navbar">
<a href="j" className="link">
Buzzify
</a>
<a href="f">
<FaRegUserCircle className="user-icon" />
</a>
</nav>
<div id="playlist-container">
<div id="playlist">
<div
className={notActive ? "icons active" : "icons"}
onClick={switchActive}
>
<BsCloudRain />
<VolSlider />
</div>
<div
className={notActive ? "icons active" : "icons"}
onClick={switchActive}
>
<GiForest />
</div>
<div className="icons">
<MdOutlineWaterDrop />
</div>
<div className="icons">
<BiWind />
</div>
<div className="icons">
<GiCampfire />
</div>
<div className="icons">
<GiThreeLeaves />
</div>
<div className="icons">
<BsMoonStars />
</div>
<div className="icons">
<BiWater />
</div>
<div className="icons">
<BiTrain />
</div>
<div className="icons">
<BiCoffeeTogo />
</div>
<div className="icons">
<FaFan />
</div>
<div className="icons">
<DiDigitalOcean />
</div>
<div className="icons">
<GiWaterfall />
</div>
<div className="icons">
<FaPlane />
</div>
<div className="icons">
<IoIosPlanet />
</div>
<div className="icons">
<GiOctopus />
</div>
</div>
</div>
</div>
);
}
CodeSandbox.io
You have two options in order to solve this:
1- You need a state for each icon that keeps track of if you clicked them or not. This could be done by making a React component that represents an icon and then use it to in your Site component:
export default function MyIcon({icon}) {
const [isActive, setIsActive] = useState(false)
return <div className={isActive ? "icons active" : "icons"}
onClick={() => {setIsActive(!isActive)}}>
{icon}
</div>
}
You can then use this component in Site() like this:
<MyIcon icon={<CertainIcon/>} />
2- You can programmatically toggle the classname "active" using the onClick event without relying on a state like this:
<div className="icons"
onClick={(event) => {event.currentTarget.classList.toggle('active')}}>
<CertainIcon/>
</div>
you should manage state per Icon like
const IconWithState = ({children}) => {
const [isActive, setIsactive] = useState(false)
const toggle = () => setIsactive(curr => !curr)
return (
<div
className={active ? "icons active" : "icons"}
onClick={toggle}
>
{children}
</div>
)
and then use it like
...
<div id="playlist-container">
<div id="playlist">
<IconWithState>
<BsCloudRain />
<VolSlider />
</IconWithState>
<IconWithState>
<GiForest />
</IconWithState>
....

React - Prevent child re-rendering in map

I have a re-render issue with a slider which appears in every element from a map.
const Attractions = () => {
const [slide, setSlide] = useState(0)
const handleSlider = (direction) => {
if(direction === "right"){
setSlide(slide + 1)
}else{
setSlide(slide - 1)
}
}
const translation = slide * - 110
return (
<div className="attractions">
<Navbar />
<Header nav={"attractions"}/>
<div className="attractionsContainer">
<div className="attractionsWrapper">
<div className="left">
</div>
<div className="right">
{attractionList.map(attraction => (
<div className="attractionWrapper" key={attraction.id}>
<div className="top">
<div className="topLeft">
<img src="https://holidaystoswitzerland.com/wp-content/uploads/2019/09/Lauterbrunnen.jpg.webp" alt="" className="avatarImg"/>
</div>
<div className="topRight">
<div className="title">{attraction.name}</div>
<div className="location"><LocationOnOutlinedIcon/>{attraction.location.city}, {attraction.location.country}</div>
</div>
<div className="moreInfo">
<MoreVertOutlinedIcon/>
</div>
</div>
<div className="middle">
<div className="sliderWrapper">
{slide > 0 &&
<div className="left" onClick={()=>handleSlider("left")}>
<ArrowBackIosNewOutlinedIcon style={{fontSize: "30px"}}/>
</div>
}
<div className="slider" style={{transform: `translateX(${translation}%)`}}>
{attraction.img.map(img =>(
<img src={img} alt="" />
))}
</div>
{slide < 2 &&
<div className="right" onClick={()=>handleSlider("right")}>
<ArrowForwardIosOutlinedIcon style={{fontSize: "30px"}}/>
</div>
}
</div>
</div>
<div className="bottom">
<div className="interactions">
<FavoriteBorderOutlinedIcon className="actionBtn"/>
<ChatBubbleOutlineOutlinedIcon className="actionBtn"/>
<CheckCircleOutlineRoundedIcon className="actionBtn"/>
<AddCircleOutlineOutlinedIcon className="actionBtn" />
</div>
<div className="description">
{attraction.description}
</div>
<div className="comments">
{attraction.comments.map(comment =>(
<div className="commentItem">
<h4>{comment.user}</h4>
<span>{comment.comment}</span>
</div>
))}
</div>
</div>
</div>
))}
</div>
</div>
</div>
<Footer />
</div>
)
}
When i get more elements from the attractionList array, whenever i click on the left or right arrow to go to the next slide, all of the sliders from the list will do the same. I figured out that i should use something so that the slide is set only based on the item from the map, but honestly i have no idea how.
If you want them to behave differently, then the attraction object should have its own slide variable and setSlide method. That way you can just put:
onclick = {() => attraction.setSlide(attraction.slide + 1)}

Next js component doesn't show without reload

Basically, I have a nested component that I want to render with the parent component and it's working fine when the server starts.
But the problem arises when I switch back from another page. Some of the nested components get disappeared. If I made a refresh then again everything ok.
How can I solve this issue?
Normal:
Image-1
Component disappeared:
Image-2
Index.js:
import BannerBaseLine from "./../components/HOME/Banner/BannerBaseLine";
import SubSection1 from "./../components/ABOUT/subSection1";
import CoursesList from "../components/HOME/MOSTTRENDING/CoursesList/courseslist";
import ShortOverview from "./../components/HOME/CourseOverviewSection/Section1/shortoverview";
import Testimonial from "./../components/HOME/Testimonial/testimonial";
import ClientItem from "./../components/HOME/Client-area/all-client-item";
export default function HomeMain({categories}) {
return (
<>
<br></br>
<br></br>
<br></br>
<BannerBaseLine categories = {categories} />
<CoursesList />
{/* <SubSection1 /> */}
<ShortOverview />
<CoursesList />
<Testimonial />
<ClientItem />
</>
);
}
export async function getStaticProps(){
const response = await fetch('http://localhost:8000/api/data/categories')
const data = await response.json()
console.log(data)
return {
props:{
categories : data,
}
}
}
BannerBaseLine component:
import BannerBlock from './BannerBlock';
export default function BannerBaseLine({ categories }) {
return (
<>
<section
className="banner-area"
style={{ backgroundImage: "url(assets/img/banner/0.jpg)" }}
>
<div className="container">
<div className="row">
<div className="col-lg-6 col-md-8 align-self-center">
<div className="banner-inner text-md-start text-center">
<h1>
Find the Best <span>Courses</span> & Upgrade{" "}
<span>Your Skills.</span>
</h1>
<div className="banner-content">
<p>
Edufie offers professional training classes and special
features to help you improve your skills.
</p>
</div>
<div className="single-input-wrap">
<input type="text" placeholder="Search your best courses" />
<button>
<i className="fa fa-search"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</section>
<br></br>
<br></br>
<div className="container">
<div className="intro-area-2">
<div className="row justify-content-center">
<div className="col-lg-12">
<div className="intro-slider owl-carousel">
{categories.map((category) => {
return (
<>
<BannerBlock category={category} key={category.id} />
</>
);
})}
</div>
</div>
</div>
</div>
</div>
</>
);
}
BannerBlock component:
export default function BannerBlock({category}) {
console.log(category);
return (
<div className="item">
<div className="single-intro-wrap">
<div className="thumb">
<img src={category.image} alt="img" />
</div>
<div className="wrap-details">
<h6>
{category.Base_Category_Title}
</h6>
<p>236 Course Available</p>
</div>
</div>
</div>
);
}
From https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation
Note: You should not use fetch() to call an API route in
getStaticProps. Instead, directly import the logic used inside your
API route. You may need to slightly refactor your code for this
approach.
Fetching from an external API is fine!
you should check if categories exist
export default function HomeMain({categories}) {
if(categories){
return <Loading Component />
}
rest of the code...
}

How to horizontalize react js component?

I created app to map all card components on a page. But components are shown vertically. I need to show 3 components per row. How can I show it like that? Here is my code.
const[item, setItem] = useState([]);
function addItem(newItem){ //This addItem Part is working.
setItem(prevItems =>{
return [...prevItems, newItem]
});
}
return(<div className="container">
<div className="row">
<div className="col-lg-4" style={{cursor: "pointer"}}>
<AddCard />
</div>
<div style={{cursor: "pointer"}}>
{item.map((items, index)=>{
return(
<div className="col-lg-4" >
<ItemCard
key={index}
id={index}
title={items.title}
description={items.description}
/>
</div>
)
})}
</div>
</div>)
You can use display:"flex" on the container
const[item, setItem] = useState([]);
function addItem(newItem){ //This addItem Part is working.
setItem(prevItems =>{
return [...prevItems, newItem]
});
}
return(<div className="container">
<div className="row">
<div className="col-lg-4" style={{cursor: "pointer"}}>
<AddCard />
</div>
<div style={{cursor: "pointer", display:"flex"}}>
{item.map((items, index)=>{
return(
<div className="col-lg-4" >
<ItemCard
key={index}
id={index}
title={items.title}
description={items.description}
/>
</div>
)
})}
</div>
</div>)
Use flexboxes, as React lets you create components, so we can style them just like HTML elements with flexboxes.
Example :
.flexbox-container {
display: flex;
flex-direction: row;
}
<div class="flexbox-container">
<div>Element1</div>
<div>Element2</div>
<div>Element3</div>
</div>

Grouping articles based on category on the same page in Gatsby JS

I have a Gatsby JS website and I would like to display on the same page a list of articles grouped by 'families' (categories, basically).
Here's what I did so far:
...
{edges.map(({ node }) => {
let families = []
_.each(edges, edge => {
if (_.get(edge, "node.frontmatter.family")) {
families = families.concat(node.frontmatter.family)
}
})
_.forEach(family => {
const articlesinfamily = () => {
return edges.filter(edge => edge.node.frontmatter.family === family)
}
return (
<>
<div className="column is-3">
<div className="content">
<div className="title is-3">
{family}
</div>
<p>Description</p>
</div>
</div>
<div className="column is-9">
<div className="columns is-multiline">
{articlesinfamily.map(({ node }) => {
<div className="column is-4">
<div className="content">
<div className="title is-4">
{node.frontmatter.name}
</div>
<p>{node.frontmatter.headline}</p>
</div>
</div>
})}
</div>
</div>
</>
)
})
})}
...
This code doesn't work but I think it's the closest I've come to a solution.
The error I get is
Expected an assignment or function call and instead saw an expression
on the line where I have {articlesinfamily.map(({ node }) => {....
Any clue on how to make this work? Is there a better way to achieve the desired result?
Thanks a lot.
This error you had in your initial question:
Expected an assignment or function call and instead saw an expression
...means that this expression inside your map:
{articlesinfamily.map(({ node }) => {
<div className="column is-4">
<div className="content">
<div className="title is-4">
{node.frontmatter.name}
</div>
<p>{node.frontmatter.headline}</p>
</div>
</div>
})}
...is effectively not being used. You are not assigning it to any variables, nor calling a function.
The solution here, as you have found in the answer you posted, is to return the expression (therefore using it in a function):
{articlesinfamily.map(({ node }) => {
return (
<div className="column is-4">
<div className="content">
<div className="title is-4">
{node.frontmatter.name}
</div>
<p>{node.frontmatter.headline}</p>
</div>
</div>
)
})}
You can also use a more concise implicit return by swapping your curly brackets for parentheses:
{articlesinfamily.map(({ node }) => (
<div className="column is-4">
<div className="content">
<div className="title is-4">
{node.frontmatter.name}
</div>
<p>{node.frontmatter.headline}</p>
</div>
</div>
))}
After further research, I solved this using Graphql 'group', like this:
Query page:
export const updatesQuery = graphql`
query {
allMarkdownRemark( filter: { frontmatter: { contentType: { eq: "updates" } } } ) {
group(field: frontmatter___family) {
fieldValue
totalCount
edges {
node {
frontmatter {
name
headline
path
}
}
}
}
}
}
`
And then in the page component I used group.map() first, and then edges.map() to catch all the 'content' inside a group. Like so:
...
{data.allMarkdownRemark.group.map(( { fieldValue, edges } ) => {
return (
<>
<div className="column is-3">
<div className="content">
<div className="title">
{fieldValue}
</div>
</div>
</div>
<div className="column is-1"></div>
<div className="column is-8">
<div className="columns is-multiline">
{edges.map(( { node } ) => {
return (
<div className="column is-4">
<div className="content">
<div className="title">{node.frontmatter.name}</div>
<p>{node.frontmatter.headline}</p>
</div>
</div>
)
})}
</div>
</div>
</>
)
})}
...
Hope this helps you as well.

Categories

Resources