I'm a React newbie, came across an interesting challenge to create "fake ecommerce page" with this api.
My Products.js file is this. I get api response and save it to a state(console logging it in one line to make sure it's working). You click on a SVG icon of + sign and that item gets "added" to the cart(don't want to add whole item for now, but just make it seems like it's adding it with setCartItems(cartItems + 1) so only number increases). Only thing is that the cart icon is in Header.js component, and I need to pass it there somehow. I've tried with props but couldn't get it to work.
Any help is very much appreciated since I want to learn from your code.
import React from 'react'
import {useState, useEffect} from 'react'
import axios from 'axios'
import plus from '../images/plus.svg'
export default function Products(props) {
const [products, setProducts] = useState([])
const [cartItems, setCartItems] = useState(0)
const updateCart = () => {
setCartItems(cartItems + 1)
console.log(cartItems)
}
useEffect(() => {
axios({
method: 'GET',
url: 'https://api.escuelajs.co/api/v1/products'
}).then((response) => {
setProducts(response.data)
console.log(response.data)
})
}, [])
return (
<section className="bg-white py-8">
<div className="container mx-auto flex items-center flex-wrap pt-4 pb-12">
<nav id="store" className="w-full z-30 top-0 px-6 py-1">
<div
className="w-full container mx-auto flex flex-wrap items-center justify-between mt-0 px-2 py-3">
<a className="uppercase tracking-wide no-underline hover:no-underline font-bold text-gray-800 text-xl "
href="#">
Store
</a>
<div className="flex items-center" id="store-nav-content">
<a className="pl-3 inline-block no-underline hover:text-black" href="#">
<svg className="fill-current hover:text-black" xmlns="http://www.w3.org/2000/svg"
width="24" height="24" viewBox="0 0 24 24">
<path d="M7 11H17V13H7zM4 7H20V9H4zM10 15H14V17H10z"></path>
</svg>
</a>
<a className="pl-3 inline-block no-underline hover:text-black" href="#">
<svg className="fill-current hover:text-black" xmlns="http://www.w3.org/2000/svg"
width="24" height="24" viewBox="0 0 24 24">
<path
d="M10,18c1.846,0,3.543-0.635,4.897-1.688l4.396,4.396l1.414-1.414l-4.396-4.396C17.365,13.543,18,11.846,18,10 c0-4.411-3.589-8-8-8s-8,3.589-8,8S5.589,18,10,18z M10,4c3.309,0,6,2.691,6,6s-2.691,6-6,6s-6-2.691-6-6S6.691,4,10,4z"></path>
</svg>
</a>
</div>
</div>
</nav>
{
products.slice(0, 20).map((product) => {
return (
<div className="w-full md:w-1/3 xl:w-1/4 p-6 flex flex-col" key={product.id}>
<div>
<img className="hover:grow hover:shadow-lg" src={product.category.image}
alt={product.description}/>
<div className="pt-3 flex items-center justify-between">
<p className="uppercase font-bold text-lg">{product.title}</p>
<img src={plus} width='20px' onClick={updateCart} alt={product.description}/>
</div>
<p className="pt-1 text-left text-gray-900">{product.price} €</p>
</div>
</div>
)
}
)
}
</div>
</section>
)
}
This is my Header.js file.
import React from 'react'
export default function Header() {
return (
<nav id="header" className="w-full z-30 top-0 py-1">
<div className="w-full container mx-auto flex flex-wrap items-center justify-between mt-0 px-6 py-3">
<label className="cursor-pointer md:hidden block">
<svg className="fill-current text-gray-900" xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 20 20">
<title>menu</title>
<path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"></path>
</svg>
</label>
<input className="hidden" type="checkbox" id="menu-toggle" />
<div className="hidden md:flex md:items-center md:w-auto w-full order-3 md:order-1" id="menu">
<nav>
<ul className="md:flex items-center justify-between text-base text-gray-700 pt-4 md:pt-0">
<li><a className="inline-block no-underline hover:text-black hover:underline py-2 px-4" href="#">Shop</a></li>
<li><a className="inline-block no-underline hover:text-black hover:underline py-2 px-4" href="#">About</a></li>
</ul>
</nav>
</div>
<div className="order-1 md:order-2">
<a className="flex items-center tracking-wide no-underline hover:no-underline font-bold text-gray-800 text-xl " href="#">
<svg className="fill-current text-gray-800 mr-2" xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 24 24">
<path d="M5,22h14c1.103,0,2-0.897,2-2V9c0-0.553-0.447-1-1-1h-3V7c0-2.757-2.243-5-5-5S7,4.243,7,7v1H4C3.447,8,3,8.447,3,9v11 C3,21.103,3.897,22,5,22z M9,7c0-1.654,1.346-3,3-3s3,1.346,3,3v1H9V7z M5,10h2v2h2v-2h6v2h2v-2h2l0.002,10H5V10z"></path>
</svg>
NORDICS
</a>
</div>
<div className="order-2 md:order-3 flex items-center" id="nav-content">
<a className="inline-block no-underline hover:text-black" href="#">
<svg className="fill-current hover:text-black" xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 24 24">
<circle fill="none" cx="12" cy="7" r="3"></circle>
<path d="M12 2C9.243 2 7 4.243 7 7s2.243 5 5 5 5-2.243 5-5S14.757 2 12 2zM12 10c-1.654 0-3-1.346-3-3s1.346-3 3-3 3 1.346 3 3S13.654 10 12 10zM21 21v-1c0-3.859-3.141-7-7-7h-4c-3.86 0-7 3.141-7 7v1h2v-1c0-2.757 2.243-5 5-5h4c2.757 0 5 2.243 5 5v1H21z"></path>
</svg>
</a>
<a className="pl-3 inline-block no-underline hover:text-black" href="#">
<svg className="fill-current hover:text-black" xmlns="http://www.w3.org/2000/svg" width="34" height="34" viewBox="0 0 24 24">
<path d="M21,7H7.462L5.91,3.586C5.748,3.229,5.392,3,5,3H2v2h2.356L9.09,15.414C9.252,15.771,9.608,16,10,16h8 c0.4,0,0.762-0.238,0.919-0.606l3-7c0.133-0.309,0.101-0.663-0.084-0.944C21.649,7.169,21.336,7,21,7z M17.341,14h-6.697L8.371,9 h11.112L17.341,14z"></path>
<circle cx="10.5" cy="18.5" r="1.5"></circle>
<circle cx="17.5" cy="18.5" r="1.5"></circle>
</svg>
<div className="inline-flex absolute top-4 justify-center items-center w-5 h-5 text-xs font-bold text-white bg-red-500 rounded-full">NUMBER OF ITEMS IN CART GOES HERE</div>
</a>
</div>
</div>
</nav>
)
}
And finally, if needed, this is my App.js file.
import './App.css';
import About from './components/About';
import Header from './components/Header';
import Hero from './components/Hero';
import Products from './components/Products';
function App() {
return (
<div className="App">
<Header />
<Hero />
<Products />
<About />
</div>
);
}
export default App;
I provide two methods for your refrence:
1.By using props:
just put your state and set function at their father element, in your situation you can put in App.js, then props to any components you want:
App.js
import './App.css';
import About from './components/About';
import Header from './components/Header';
import Hero from './components/Hero';
import Products from './components/Products';
import axios from 'axios'
function App() {
const [products, setProducts] = useState([]) // put here
const [cartItems, setCartItems] = useState(0) // put here
// get your api here
useEffect(() => {
axios({
method: 'GET',
url: 'https://api.escuelajs.co/api/v1/products'
}).then((response) => {
setProducts(response.data)
})
}, [])
return (
<div className="App">
<Header setCartItems={setCartItems} cartItems={cartItems}/>
<Hero />
<Products cartItems={cartItems} setCartItems={setCartItems} products={products} setProducts={setProducts}/>
<About />
</div>
);
}
export default App;
after then in your Products.js and Header.js can get props data, and can get props set feunction to update state.
But I think put global state is better,
I recommend useContext or zustand to do it!
2.Put in zustand:
create file named store.js, then npm install zustand
store.js
import create from 'zustand';
// this is our useStore hook that we can use in our components to get parts of the store and call actions
const useStore = create((set, get) => ({
cartItems: 0,
setCartItems: (value) =>
set((state) => ({
cartItems: value,
})),
}));
export default useStore;
Product.js and Header.js add below code:
import useStore from './store'; // import the store you writed before
export default function Products(props) {
// get your store state and function
const { cartItems, setCartItems } = useStore();
// update your store state
const updateCart = () => {
setCartItems(cartItems + 1)
}
const minusCart = () => {
setCartItems(cartItems - 1)
}
//...your other code
}
You either need to use global state management like redux or pass a callback function from the header to the products component to update the state. React is unidirectional data flow downward, so you can't pass props back up like you can from parent to child.
How to fix this index.tsx:25 No routes matched location "/Reel/src/App" i want that when a user click on the image than reels start playing so when i add but now the error is coming in console index.tsx:25 No routes matched location "/Reel/src/App" how to fix that inside my social media app project i have one reels project means their are two projects pls tell the image pls tell how to fix this at least try to fix this problem..
import { Header } from "../../features/theme/Header";
import styles from "./Home.module.css";
import { useAppSelector } from "../../app/hooks";
import { Feed } from "../../features";
import { Link } from "react-router-dom";
import './Reel/src/App'
export function Home(): JSX.Element {
const { currentUserImage } = useAppSelector((state) => state.currentUser);
return (
<div className={styles.home}>
<Header page="Home" />
<div className={styles.tweetField}>
<div className={styles.userAvatar}>
<img src={currentUserImage} alt="" />
<h1>Mowe</h1>
</div>
<Link to="/Reel/src/App">
<div className={styles.userAvatar}>
<img src={currentUserImage} alt=""/>
<h1>Haewae</h1>
</div>
</Link>
<div className={styles.userAvatar}>
<img src={currentUserImage} alt="" />
<h1> Lveewe</h1>
</div>
<div className={styles.userAvatar}>
<img src={currentUserImage} alt=""/>
<h1>gy</h1>
</div>
<div>
<div>
</div>
</div>
</div>
<Feed />
</div>
);
}
I want that if a user click on the marked image than reels start playing on other page for eg YouTube shorts so i first added a on click on the image and imported app.js file from the reels folder but it is not working so is their any way to do that pls if you are not sure about how to do that at least try if you didn't work no problem we will get a way that didn't work. just try!
i am not a very good programmer
image
import { Header } from "../../features/theme/Header";
import styles from "./Home.module.css";
import { useAppSelector } from "../../app/hooks";
import { Feed } from "../../features";
export function Home(): JSX.Element {
const { currentUserImage } = useAppSelector((state) => state.currentUser);
return (
<div className={styles.home}>
<Header page="Home" />
<div className={styles.tweetField}>
<div className={styles.userAvatar}>
<img src={currentUserImage} alt="" />
<h1>Mowe</h1>
</div>
<div className={styles.userAvatar}>
<img src={currentUserImage} alt="" />
<h1>Haewae</h1>
</div>
<div className={styles.userAvatar}>
<img src={currentUserImage} alt="" onClick={reels}/>
<h1> Lveewe</h1>
</div>
<div className={styles.userAvatar}>
<img src={currentUserImage} alt=""/>
<h1>gy</h1>
</div>
<div>
<div>
</div>
</div>
</div>
<Feed />
</div>
);
}
<a href="YOUTUBE-SHORTS-LINK" className={styles.userAvatar}>
<img src={currentUserImage} alt="" />
<h1> Lveewe</h1>
</a>
or
<a href="YOUTUBE-SHORTS-LINK">
<div className={styles.userAvatar}>
<img src={currentUserImage} alt="" />
<h1> Lveewe</h1>
</div>
</a>
I'm making my web resume using react having parent div like this -
<div
className={`w-100 d-flex flex-column align-items-center m-0 position-absolute ${styles.container} `}
>
In this I have multiple child div but when I run my code the elements of div are scrolling rather than the page.When I give height to parent div but it's not working fine on some browsers.I need a good solution so that elements remain static and page scrolls.
Thanks in advance.
https://utkarsh0911.github.io/my_web_resume/
Remove the background-attachement propery of the class 'landing_container__23Tq8' in your css.
You can try to update src/Pages/LandinPage.js with the following snippet.
import React, { Component ,Text,StyleSheet} from 'react'
import Logo from '../Images/SiteLogo/logo.jpg'
import MyNav from '../Components/MyNav'
import styles from '../css/landing.module.css'
import { Button, Container } from 'react-bootstrap'
import MyButton from '../Components/MyButton'
import Myphoto from '../Images/MyPhoto/photo.png'
import MyRoundedImage from '../Components/MyRoundedImage'
import AboutMe from './AboutMe'
import Experience from './Experience'
import Skills from './Skills'
import MySimpleImage from '../Components/MySimpleImage'
import Education from './Education'
import resume from '../docs/resume.pdf'
import MyFooter from '../Components/MyFooter'
import MyJumbo from '../Components/MyJumbo'
class LandingPage extends Component
{
render() {
return (
<div className={ `w-100 d-flex flex-column align-items-center m-0 position-absolute ${styles.container} `} >
<div className="container ">
<MyNav title="MyResume" items={["ABOUT","BLOG","CONTACT"]}/>
</div>
<div className="d-flex justify-content-center ">
<h1 className={`font-weight-bold text-white text-center ${styles.h1}`}>WELCOME TO MY STUDIO!!</h1>
</div>
<div className="d-flex flex-wrap justify-content-center mt-2 ">
<a href={resume} target="_blank" rel="noopener noreferrer" download>
<MyButton title="Download CV" variant="success"/></a>
<MyButton title="Subscribe" variant="success"/>
</div>
<div className="d-flex flex-wrap clearfix mt-1 flex-wrap justify-content-center align-items-center">
<MyRoundedImage src={Myphoto}/>
</div>
<div className="bg-white">
<AboutMe />
<MyJumbo title="EXPERIENCE"/>
<div className={styles.expContainer}>
<Experience/>
</div>
<MyJumbo title="SKILLS"/>
<Skills/>
<MyJumbo title="EDUCATION"/>
<Education/>
</div>
{/* <MyFooter/> */}
</div>
)
}
}
export default LandingPage
Basically, the scrolling is fine; however, a background is missing from the About Me section onwards.
Good Luck...
I'm new to VueJS, and I'm coming to you to find out if what I've done is feasible or not.
Instead of having old data, while loading components, I prefer to display a preloader.
I liked the idea of a skeletons loader, rather than a simple spinner.
Right now I have a state in the store, which is null by default, I have a mutation to set the loading, and a getter.
To avoid visual bugs, from the router, with a beforeEach, I initialize the loading state to true, so that by default the components start loading !
Then, in my view, I import the Loader component, with its svg and style.
And I place it over the component that needs to be displayed, with a simple condition v-if="!getLoading" and v-if="getLoading".
The problem is that I feel like I'm tinkering with the blind, the beforeach and displaying this component with a condition?
I would be reassured if someone can give me some advice, or approve this method of doing!
Here is the code of a simple Loader component
<template>
<content-loader
:height="78"
:width="390"
:speed="4"
primaryColor="#f2f6fe"
secondaryColor="#e0eafa"
>
<rect x="9" y="20" rx="4" ry="4" width="142" height="13" />
<rect x="316.38" y="5.38" rx="5" ry="5" width="68" height="68" />
<rect x="9" y="46" rx="4" ry="4" width="75.26" height="13.26" />
</content-loader>
</template>
<script>
import { ContentLoader } from "vue-content-loader"
export default {
components: {
ContentLoader
}
}
</script>
The store code
const state = {
loading: null,
}
const mutations = {
SET_LOADING: (state, payload) => {
state.loading = payload;
},
}
const getters = {
getLoading(state) {
return state.loading;
}
}
Example of utilisation in my view : with condition
<div class="col-12 col-lg-4 col-xl-3 col-md-6" v-if="getLoading"> // the condition
<div class="card animate-up-2">
<div class="card-body">
// the component
<StatsLoader></StatsLoader>
</div>
</div>
</div>
<div class="col-12 col-lg-4 col-xl-3 col-md-6" v-if="!getLoading"> // the condition
<div class="card animate-up-2">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between">
<div>
<h3 class="font-weight-bold text-uppercase">5 %</h3>
<div class="d-flex d-sm-block d-lg-flex align-items-end">
<p class="mb-0 mr-2 text-muted">API usage</p>
</div>
</div>
<div>
<div class="avatar avatar-lg">
<div class="avatar-title sred sbg-soft-red rounded">
<i class="fad fa-project-diagram"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
If that is a global loader being used on all the routes, you can wrap it in a component and use that component everywhere. Use named slots to manage your template.
An example of a Loader component:
Loader.vue
<template>
<div>
<slot name='loading' v-if='getLoading'>
<StatsLoader></StatsLoader>
</slot>
<slot name='content v-if='!getLoading'></slot>
</div>
</template>
<script>
import StatsLoader from '#/components/StatsLoader.vue';
export default {
name: 'Loader',
props: {
isLoading: {
type: Boolean,
default: null
}
},
computed: {
getLoading() {
return this.isLoading === null ? this.$store.state.loading : this.isLoading;
}
},
components: {
StatsLoader
}
}
</script>
Also, it would useful to register this component globally so you don't need to include it all the routes. You can do that using Vue.component in your main entry file.
import Loader from '#/components/Loader.vue';
Vue.component('Loader', Loader);
And you can rewrite your current component template like this:
<Loader>
<template v-slot:loader>
<!-- Use a different loader here for this page maybe -->
</template>
<template v-slot:content>
<div class="card animate-up-2">
<div class="card-body">
<div class="d-flex align-items-center justify-content-between">
<div>
<h3 class="font-weight-bold text-uppercase">5 %</h3>
<div class="d-flex d-sm-block d-lg-flex align-items-end">
<p class="mb-0 mr-2 text-muted">API usage</p>
</div>
</div>
<div>
<div class="avatar avatar-lg">
<div class="avatar-title sred sbg-soft-red rounded">
<i class="fad fa-project-diagram"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
</Loader>
Also you can use <Loader :is-loading='isPageLoading' /> in case you don't want to rely on the global loader.