I am beginner in react.
I am making a small project. How to add Product in cart and I am stuck at re Rendering useEffect.
so what I want is to re Render the useEffect on button click.
how do I do that?
Here Is my Cart Component
import React, { useContext, useEffect, useState,useCallback } from "react";
import { UserContext } from "./Context";
import { useHistory } from "react-router";
import cartImage from "../assets/man-shopping.png";
import Axios from "axios";
const Cart = () => {
const { user, serUser } = useContext(UserContext);
const history = useHistory();
const [product, setProduct] = useState([]);
const removeFromCart = (item) => {
Axios.delete(`http://localhost:3002/cart/${item.Id}`).then((res) => {
setProduct(
product.filter((item) => {
return item.Id !== res.data.Id;
})
);
});
};
useEffect(() => {
Axios.get(`http://localhost:3002/cart/${user.Id}`).then((res) => {
setProduct(res.data);
});
}, [user]);
return (
<div
className="d-flex align-items-center justify-content-center"
style={{ height: "90vh" }}
>
{user.role === undefined ? (
<div>
<button
className="btn btn-lg btn-primary bg-green"
onClick={() => {
history.push("/login");
}}
>
Please Login
</button>
</div>
) : (
<div>
{product.length === 0 ? (
<figure className="figure">
<img
src={cartImage}
alt="cart"
style={{ width: "100px", height: "100px" }}
/>
<figcaption className="figure-caption text-xs-right">
No Product Added
</figcaption>
</figure>
) : (
<div className="d-flex">
{product.map((item) => {
return (
<div className="card">
<img
src={new Buffer.from(item.pimg).toString("ascii")}
className="img-fluid crd-img"
/>
<div className="card-body">
<h5 className="card-title">{item.pname}</h5>
<p className="card-text">{item.pprice}</p>
<button
className="btn btn-primary"
onClick={() => removeFromCart(item)}
>
Remove
</button>
</div>
</div>
);
})}
</div>
)}
</div>
)}
</div>
);
};
export default Cart;
so I made the removeFromCart function as useEffect dependency so it works fine
but its calls the backend again and again.
const removeFromCart = (item) => {
Axios.delete(`http://localhost:3002/cart/${item.Id}`).then((res) => {
setProduct(
product.filter((item) => {
return item.Id !== res.data.Id;
})
);
});
};
useEffect(() => {
Axios.get(`http://localhost:3002/cart/${user.Id}`).then((res) => {
setProduct(res.data);
});
}, [user,removeFromCart]);
Is there any other way to re render useEffect
Put axios.get in a function.
const getProduct = useCallback(() => {
Axios.get(`http://localhost:3002/cart/${user.Id}`).then((res) => {
setProduct(res.data);
});
}, [user]);
const removeFromCart = (item) => {
Axios.delete(`http://localhost:3002/cart/${item.Id}`).then((res) => {
getProduct();
});
};
useEffect(() => {
getProduct();
}, [getProduct]);
What you need is not useEffect. Use a 'state' to store the items and add or delete items using setState when 'state' gets updated react will automatically re-render. And you can use the updated state to save in your database. Also update state before calling axios
You can add a boolean state like this :
const [isClicked, setIsCliked] = useState(false);
And toogle the boolean value whenever the button is clicked
const removeFromCart = (item) => {
Axios.delete(`http://localhost:3002/cart/${item.Id}`).then((res) => {
setProduct(
product.filter((item) => {
return item.Id !== res.data.Id;
})
);
setIsCliked(bool => !bool)
});
};
And your useEffect may now look like this :
useEffect(() => {
Axios.get(`http://localhost:3002/cart/${user.Id}`).then((res) => {
setProduct(res.data);
});
}, [user.id,isClicked]);
There must be a better way but this should work
Related
So I have an array of images, which I would like to hide or show on a click of a button.
right now when I try to hide the image, it will hide the entire array.
import "./main.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import React, { useEffect, useState } from "react";
import {
faCircleChevronLeft,
faCircleChevronRight,
faCircleXmark,
} from "#fortawesome/free-solid-svg-icons";
const Main = ({ galleryImages }) => {
const [slideNumber, setSlideNumber] = useState(0);
const [openModal, setOpenModal] = useState(false);
const [pics, setPics] = useState([]);
const [show, toggleShow] = useState(true);
// buttons next to name of diff charts (hide/show chart)
const handleOpenModal = (index) => {
setSlideNumber(index);
setOpenModal(true);
};
const removeImage = (id) => {
setPics((oldState) => oldState.filter((item) => item.id !== id));
};
// const hide = () => {
// setShow(false)
// }
const handleCloseModal = () => {
setOpenModal(false)
}
useEffect(()=> {
setPics(galleryImages)
},[]);
return (
<div>
<button onClick={() => toggleShow(!show)}>toggle: {show ? 'show' : 'hide'}</button>
{show &&
<div>
{pics.map((pic) => {
return (
<div style = {{marginBottom:'100px'}}>
{pic.id}
<img
src={pic.img}
width='500px'
height='500px'
/>
<button onClick ={() => removeImage(pic.id)}>Delete</button>
</div>
)
})}
</div>
I tried making a state component to try to hide and show the images, however it will hide the entire array instead of the individual image
i would add a show var to the galleryImages array and then set it so you get control of each image like this
import { useState } from "react";
import { v4 as uuidv4 } from "uuid";
import "./main.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import React, { useEffect, useState } from "react";
import {
faCircleChevronLeft,
faCircleChevronRight,
faCircleXmark,
} from "#fortawesome/free-solid-svg-icons";
function Main({ galleryImages }) {
const [slideNumber, setSlideNumber] = useState(0);
const [openModal, setOpenModal] = useState(false);
const [pics, setPics] = useState([]);
// buttons next to name of diff charts (hide/show chart)
const toggleShow = ({ id, show }) => {
setPics((oldState) =>
oldState.map((item) => {
if (item.id !== id) return item;
return { ...item, show: !show };
})
);
};
const removeImage = (id) => {
setPics((oldState) => oldState.filter((item) => item.id !== id));
};
useEffect(() => {
setPics(
galleryImages.map((galleryImage) => {
return { ...galleryImage, show: true };
})
);
}, []);
return (
<div>
<div>
{pics.map((pic) => {
return (
<>
<button
onClick={() => toggleShow({ show: pic.show, id: pic.id })}
>
toggle: {pic.show ? "show" : "hide"}
</button>
{pic.show && (
<div style={{ marginBottom: "100px" }}>
{pic.id}
<img src={pic.img} width="500px" height="500px" />
<button onClick={() => removeImage(pic.id)}>Delete</button>
</div>
)}
</>
);
})}
</div>
</div>
);
}
export default Main;
`
If you would like the option to hide individual pics, to accomplish this you are correct in your state component approach.
First you can create a pic component that has its own state with a hide/show button:
export default function Pic({pic}) {
const [showPic, setShowPic] = useState(true);
const handleClick = () => {setShowPic(!showPic)}
return (
<div>
<div style={showPic ? {display : "block"} : {display : "none"}}>
<img
src={pic.img}
width='500px'
height='500px'
/>
</div>
<button onClick={handleClick}>{showPic ? 'Hide' : 'Show'}</button>
</div>
)
}
Next, you can import this component into your main file
import Pic from 'location/Pic.js';
and map each pic to a <Pic> component.
{pics.map((pic) => <Pic pic={pic} key={pic.id}/>)}
Now the images will be shown each with their own Hide/Show button that can toggle their display with the state contained within each <Pic/> component. This is good practice because toggling one image will not cause a re-render of the entire image gallery.
i don't know how can i print user info react modal
this is my code
import React from "react";
import axios from "axios";
import { useEffect, useState } from "react";
import { Show, User } from "../api";
import UseUser from "../scroll/userInfo";
function ShowContents() {
const [storyIds, setStoryIds] = useState([]);
const [visible, setVisible] = useState(false);
const [getUser, setGetUser] = useState([]);
useEffect(() => {
Show().then((res) => {
this.res = res.data.slice(0, 10);
this.res.forEach(async (ele) => {
await axios
.get("https://hacker-news.firebaseio.com/v0/item/" + ele + ".json")
.then((res) => {
if (Array.isArray(this.res) && this.res.length === 0) {
return;
} else {
setStoryIds((value) => [
...value,
{
id: res.data.id,
title: res.data.title,
url: res.data.url,
user: res.data.by,
score: res.data.score
}
]);
}
});
});
});
}, []);
const menu = storyIds;
const menuList = menu.map((m, i) => (
<div className="box_show" key={i}>
<div className="flex">
<p className="numbers">{i + 1}</p>
<a href={m.url} className="titleFont">
{m.title}
</a>
<a href={m.url}>
<img src={`/assets/back.svg`} alt="" className="imgLink" />
</a>
</div>
<br />
<button
className="userShow"
onClick={() => {
setVisible(!visible);
}}
>
<div className="userNameShow">{m.user}</div>
</button>
</div>
));
return (
<>
{menuList}
{visible && (
<div className="modal-container" id="modal">
<div className="modal">
<div className="modal-top flex">
<p>User Info</p>
<button
className="close-btn"
onClick={() => {
setVisible(!visible);
}}
>
<img src={`/assets/close_black.svg`} alt="" />
</button>
</div>
<UseUser />
</div>
</div>
)}
</>
);
}
export default ShowContents;
The code above is my show partial code.
this is my UserInfo code
import { useState, useEffect } from "react";
import { getUser } from "../api";
const UseUser = (id) => {
// const [user, setUser] = useState({});
// useEffect(() => {
// getUser(id).then((user) => setUser(user));
// }, [id]);
return (
<>
<div className="user-detail flex">
<div className="user-profile"></div>
<div className="user-detail-info">
<p className="modal-user">user : </p>
<p className="modal-created">created : </p>
<p className="modal-karma">karma : </p>
</div>
</div>
<p className="about">about:</p>
<p className="email">Twitter:</p>);
</>
);
};
export default UseUser;
import axios from "axios";
const BASE_URL = "https://hacker-news.firebaseio.com/v0/";
export const storyUrl = `${BASE_URL}item/`;
function News() {
return axios.get(`${BASE_URL}newstories.json`);
}
function Jobs() {
return axios.get(`${BASE_URL}jobstories.json`);
}
function Top_API() {
return axios.get(`${BASE_URL}topstories.json`);
}
function Ask() {
return axios.get(`${BASE_URL}askstories.json`);
}
function Show() {
return axios.get(`${BASE_URL}showstories.json`);
}
function User() {
return axios.get(`${BASE_URL}user`);
}
export { News, Jobs, Top_API, Ask, Show, BASE_URL, User };
this is my api code
When you click the user button in the show part, I want to get information about the user. It's too difficult for me right now.
I tried to implement it using use Effect, but I don't know how to send information about the user when I press the button.
I need help.
I'm trying to create a simple Cart using Redux, but removeFromCart() function throws an error.
I have created a cartActions.js file with two dispatch functions, addToCart() function that works as it should and removeFromCart() function that returns TypeError: getState is not a function.
How can I fix this problem ?
This is the cartActions.js file:
import { ADD_TO_CART, REMOVE_FROM_CART } from "../types";
export const addToCart = (product) => (dispatch, getState) => {
const cartItems = getState().cart.cartItems.slice();
let alreadyExists = false;
cartItems.forEach((x) => {
if (x._id === product._id) {
alreadyExists = true;
x.count++;
}
});
if (!alreadyExists) {
cartItems.push({ ...product, count: 1 });
}
dispatch({
type: ADD_TO_CART,
payload: { cartItems },
});
localStorage.setItem("cartItems", JSON.stringify(cartItems));
console.log(cartItems)
};
export const removeFromCart = (product) => (dispatch, getState) => {
const cartItems = getState().cart.cartItems.slice()
.filter((x) => x._id !== product._id);
dispatch({
type: REMOVE_FROM_CART,
payload: { cartItems },
});
localStorage.setItem("cartItems", JSON.stringify(cartItems));
};
This is the error that I get:
24 |
25 | export const removeFromCart = (product) => (dispatch, getState) => {
> 26 | const cartItems = getState().cart.cartItems.slice()
27 | .filter((x) => x._id !== product._id);
28 | dispatch({
29 | type: REMOVE_FROM_CART,
The error occurs when the cart component is supposed to render.
I have a function openCart() that alternate between rendering the "Shop" and "Cart" when I press the button the error occurs
This is the openCart() function:
openCart = () => {
this.setState({openCartStatus:!this.state.openCartStatus});
} // the function starts with openCartStatus as false
The cart.js file is long but I think it’s necessary to include it for reference.
I used react hooks for cart.js.
this is the cart.js:
import React, { useRef } from 'react';
import './cart.css'
import { useIntersection } from 'react-use';
import formatCurrency from '../../../util'
import { Fade } from "react-awesome-reveal";
import { connect } from 'react-redux';
import { removeFromCart } from '../../../actions/cartActions';
function Cart (props) {
const sectionRef = useRef(null);
const intersection = useIntersection(sectionRef, {
root: null,
rootMargin: "80%",
threshold: 0.8,
});
const { cartItems } = props;
return (
<div className="container" >
<div className="cart_container" ref={sectionRef}>
<div className="cart_icon_container">
<div className={intersection && intersection.intersectionRatio < 0.5 ? "cart_Icon" : "cart_Icon_Btn"} onClick={() => {
props.openCart();
}}>
<img alt='cart-icon' src='./Images/icons8-shopping-bag-32.png' ></img>
</div>
</div>
{cartItems.length === 0 ? (
<div className="cart cart_header">
Cart Is Empty
</div>
) : (
<div className="cart cart_header">
You Have {cartItems.length} Itames In The Cart{""}
</div>
)}
<div>
<div className="cart">
<Fade direction="up" triggerOnce cascade duration="750">
<ul className="cart_items">
{cartItems.map((item , index ) => (
<li key={index}>
<div className="cart_image">
<img src={item.image} alt={item.name}></img>
</div>
<div className="ShopItem_details_discription">
<div className="productInfo_Container">
<div> LOGO </div>
<div className="productInfo">
<h2>{item.name}</h2>
<p>{item.info}</p>
</div>
<div >
<p> Phone Number</p>
<div className="flourType_Container" >
{item.flourType.map((x)=>(
<div>{" "}{x}</div>
))}
</div>
</div>
</div>
</div>
<div className="cart_mengment">
{formatCurrency(item.price)}
<div className="btn_containar">
<button onClick={() => props.addAmount(item)} className = "Btn" > + </button>
<div className = "ItemCounte"> {item.count}</div>
<button onClick={() => props.subAmount(item, index)} className = "Btn" > - </button>
</div>
<button className="cart_item_remove" onClick={() => props.removeFromCart(index)}>
Remove
</button>
</div>
</li>
))}
</ul>
</Fade>
</div>
</div>
{cartItems.length !== 0 && (
<div className="cart">
<div className="total">
<div >
TOTAL{" "}
{formatCurrency(
cartItems.reduce((a, c) => a + c.price * c.count, 0)
)}
</div>
<button className="proceed_Btn" onClick={() => {
props.showCheckout();
}}>
Proceed
</button>
</div>
</div>
)}
</div>
</div>
)
}
export default connect((state) => ({
cartItems: state.cart.cartItems,
}),
removeFromCart
)(Cart);
You need to pass object as mapDispatchToProps in connect method instead of just removeFromCard.
export default connect((state) => ({
cartItems: state.cart.cartItems,
}),
{ removeFromCart }
)(Cart);
Read: https://react-redux.js.org/using-react-redux/connect-mapdispatch
Your case scenario is essentially the first example. You don't need to pass your removeFromCart function to the component as it's already available due to your import.
If you remove the 2nd argument from connect, Redux's dispatch function is passed as a prop. So you'd need to change
export default connect((state) => ({
cartItems: state.cart.cartItems,
}),
removeFromCart
)(Cart);
to
export default connect((state) => ({
cartItems: state.cart.cartItems,
}))(Cart);
and
<button className="cart_item_remove" onClick={() => props.removeFromCart(index)}>Remove</button>
to
<button className="cart_item_remove" onClick={() => props.dispatch(removeFromCart(index))}>Remove</button>
and it should work as expected (at least the getState function should work).
Tip: Look at Redux lifecycle implementations, Redux is incredibly complex at first glance but after you simplify the implementation with standards...it's really easy. I'd look at mapStateToProps, mapDispatchToProps in the link above.
Example
Component.js
export function Component({ hello, setHello }) {
return <>
<p>{hello}</p>
<button onClick={() => setHello('Bye')}>
</>
}
container.js
import { connect } from 'react-redux';
import { Component } from './Component.js';
import { setHello } from './action.js';
const mapStateToProps = (state, ownProps) => {
return {
hello: state.hello
}
}
const mapDispatchToProps = (dispatch) => {
return {
setHello: (input) => {
dispatch(setHello(input));
}
}
}
connect(mapStateToProps, mapDispatchToProps)(Component);
to watch the problem you can vivsit the test site http://u100525.test-handyhost.ru/products
the problem appears if to click many times on category items, images of products start to bug becouse react loads image of one item over and over again, on every change of category - on every filter of products, so how to make one load and save somehow the loaded images?
so if i click on categories my code is filtering products array and update statement - visibleProducts then im doing visibleProducts.map((product)=>{});
and i`m getting bug problem, because every time when react renders my the component does request to the server for getting image by id and waits while the image will load, but if i click on an other category react(ProductItem) starts other request for new images then it is starting to bug they start blinking and changing ;c
im new in react and just stated to practice what i have to do guys?
is my code correct ?
here is my ProductItem component ->
import React, { useState, useEffect, memo, useCallback } from "react";
import { Link } from "react-router-dom";
import { connect } from "react-redux";
import { setModalShow, onQuickViewed, addedToCart } from "../../actions";
import Checked from "../checked";
import "./product-item.css";
import Spinner from "../spinner";
const ProductItem = ({
product,
wpApi,
addedToCart,
onQuickViewed,
setModalShow,
}) => {
const [prodImg, setProdImg] = useState("");
const [animated, setAnimated] = useState(false);
const [checked, setChecked] = useState(false);
const [itemLoading, setItemLoading] = useState(true);
const checkedFn = useCallback(() => {
setChecked(true);
setTimeout(() => {
setChecked(false);
}, 800);
},[product]);
const onModalOpen = useCallback((e, id) => {
onQuickViewed(e, id);
setModalShow(true);
}, product);
const addHandle = useCallback((e, id) => {
e.preventDefault();
addedToCart(id);
checkedFn();
},[product]);
useEffect(()=>{
setItemLoading(false);
}, [prodImg]);
useEffect(() => {
wpApi.getImageUrl(product.imageId).then((res) => {
setProdImg(res);
});
});
return (
<div className="product foo">
<div
className='product__inner'}
>
{!itemLoading? <div
className="pro__thumb"
style={{
backgroundImage:prodImg
? `url(${prodImg})`
: "assets/images/product/6.png",
}}
>
<Link
to={`/product-details/${product.id}`}
style={{ display: `block`, width: `100%`, paddingBottom: `100%` }}
>
</Link>
</div>: <Spinner/>}
<div className="product__hover__info">
<ul className="product__action">
<li>
<a
onClick={(e) => {
onModalOpen(e, product.id);
}}
title="Quick View"
className="quick-view modal-view detail-link"
href="#"
>
<span ><i class="zmdi zmdi-eye"></i></span>
</a>
</li>
<li>
<a
title="Add TO Cart"
href="#"
onClick={(e) => {
addHandle(e, product.id);
}}
>
{checked ? (
<Checked />
) : (
<span className="ti-shopping-cart"></span>
)}
</a>
</li>
</ul>
</div>
</div>
<div className="product__details">
<h2>
<Link to={`/product-details/${product.id}`}>{product.title}</Link>
</h2>
<ul className="product__price">
<li className="old__price">${product.price}</li>
</ul>
</div>
</div>
);
};
const mapStateToProps = ({ options, cart, total, showModal }) => {
return {};
};
const mapDispatchToProps = {
onQuickViewed,
setModalShow,
addedToCart,
};
export default connect(mapStateToProps, mapDispatchToProps)(memo(ProductItem));
here is my parent component Products ->
import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import ProductItem from "../product-item";
import { withWpApiService } from "../hoc";
import { onQuickViewed, addedToCart, categoriesLoaded } from "../../actions";
import CategoryFilter from "../category-filter";
import Spinner from "../spinner";
import "./products.css";
const Products = ({
maxProducts,
WpApiService,
categoriesLoaded,
addedToCart,
onQuickViewed,
products,
categories,
loading,
}) => {
const [activeIndex, setActiveIndex] = useState(0);
const [activeCategory, setActiveCategory] = useState(0);
const [visibleProducts, setVisibleProducts] = useState([]);
const wpApi = new WpApiService();
useEffect(() => {
updateVisibleProducts(activeCategory, products);
}, [products]);
useEffect(() => {
wpApi.getCategories().then((res) => {
categoriesLoaded(res);
});
}, []);
const getCatId = (cat) => {
setActiveCategory(cat);
updateVisibleProducts(cat, products);
setActiveIndex(cat);
};
const updateVisibleProducts = (category, products) => {
let updatedProducts = [];
switch (category) {
case 0:
updatedProducts = products;
setVisibleProducts(updatedProducts);
break;
default:
updatedProducts = products.filter(
(product) => product.categories.indexOf(category) >= 0
);
setVisibleProducts(updatedProducts);
}
};
let currentLocation = window.location.href.split("/");
if (!loading) {
return (
<section className="htc__product__area shop__page mb--60 mt--130 bg__white">
<div className={currentLocation[3] == "" ? `container` : ""}>
<div className="htc__product__container">
<CategoryFilter
activeIndex={activeIndex}
categories={categories}
getCatId={getCatId}
/>
<div
className="product__list another-product-style"
style={{ height: "auto" }}
>
{visibleProducts
.slice(0, maxProducts ? maxProducts : products.length)
.map((prod, id) => {
return (
<ProductItem
wpApi={wpApi}
key={id}
onQuickViewed={onQuickViewed}
addedToCart={addedToCart}
product={prod}
/>
);
})}
</div>
</div>
</div>
</section>
);
} else {
return <Spinner />;
}
};
const mapStateToProps = ({ products, loading, activeCategory, categories }) => {
return {
products,
activeCategory,
categories,
loading,
};
};
const mapDispatchToProps = {
addedToCart,
categoriesLoaded,
onQuickViewed,
};
export default withWpApiService()(
connect(mapStateToProps, mapDispatchToProps)(Products)
);
and if you need, here is my CategoryFilter component ->
import React from 'react'
const CategoryFilter = ({categories, getCatId, activeIndex}) => {
return (
<div className="row mb--60">
<div className="col-md-12">
<div className="filter__menu__container">
<div className="product__menu">
{categories.map((cat) => {
return (
<button key={cat.id}
className={activeIndex === cat.id? 'is-checked' : null}
onClick={() => getCatId(cat.id)}
data-filter=".cat--4"
>
{cat.name}
</button>
);
})}
</div>
</div>
</div>
</div>
)
}
export default CategoryFilter
I got this component in React.js which make different kinds of filtering when I click a button, this is my code:
import React, { useContext } from 'react';
import { ModelsContext } from "../context/ModelsContext";
const FilterNav = () => {
const { modelos, guardarModelo } = useContext(ModelsContext);
const filterSegment = e => {
const segment = modelos.filter(modelo => modelo.segment === e.target.name);
guardarModelo(segment);
}
return (
<nav className="filter-container">
<div className="container">
<h3 className="filter-element-title">Filtrar por</h3>
<button type="button" className="filter-element">Todos</button>
<button type="button" className="filter-element" name="Autos" onClick={filterSegment}>Autos</button>
<button type="button" className="filter-element" name="Pickups y Comerciales" onClick={filterSegment}>Pickups y Comerciales</button>
<button type="button" className="filter-element" name="SUVs y Crossovers" onClick={filterSegment}>SUVs y Crossovers</button>
</div>
<p className="filter-element-last">Ordenar por ^</p>
</nav>
);
}
export default FilterNav;
The information I get from the api with useContext in ModelsContext.jsx, here is what I wrote so far:
import React, { createContext, useState, useEffect } from 'react';
export const ModelsContext = createContext();
const ModelsProvider = (props) => {
//State de modelos
const [modelos, guardarModelo] = useState([]);
const consultarAPI = async () => {
const api = await fetch("https://challenge.agenciaego.tech/models");
const modelos = await api.json();
guardarModelo(modelos);
}
//Cargar un modelo
useEffect(() => {
consultarAPI()
}, []);
return (
<ModelsContext.Provider
value={{
modelos,
guardarModelo
}}
>
{props.children}
</ModelsContext.Provider>
)
}
export default ModelsProvider;
My issue is that when I filter the API modelos throught the filterSegment function I don't know how to re-fetch the data from the API, because when I do a new call to the filterSegment function it filters the filtered data. I've tried to add a boolean state, and I was thinking about adding another state with allthedata, but I really lost about implementing it, I'm still very new to React.js.
I've search through stack overflow and google and I cannot get the answer, If you can give me a clue or some sort of guidance it will be appreciated.
Thanks so much!
You can add another state in the ModelsContext:
//State de modelos
const [modelos, guardarModelo] = useState([]);
const [allModelos, guardarAllModelo] = useState([]);
const consultarAPI = async () => {
const api = await fetch("https://challenge.agenciaego.tech/models");
const modelos = await api.json();
guardarAllModelo(modelos);
//uncomment if you want to have initial value for modelos state
//guardarModelo(modelos);
}
// some codes ...
<ModelsContext.Provider
value={{
allModelos,
modelos,
guardarModelo
}}
>
{props.children}
</ModelsContext.Provider>
Then in the FilterNav component:
const {allModelos, modelos, guardarModelo } = useContext(ModelsContext);
const filterSegment = e => {
const segment = allModelos.filter(modelo => modelo.segment === e.target.name);
guardarModelo(segment);
}
But this does not really re-fetch data from your web api. It just re-filters the first fetched data. if you want to re-fetch data from web api you can add consultarAPI in your context provider then call it somewhere.
Thanks code is working
This is my Portfolio gallery code First time load all data when click category then get category dataenter code here
Thanks code is working
This is my Portfolio gallery code First time load all data when click category then get category data`enter code here`
import React, { Component, useEffect, useState } from 'react'`enter code here`;
import Thumnailport_list from './Thumnailport_list';
import Portlightbox from './Portlightbox';
import Functional from './Functional';
import $ from 'jquery';
const Portfolio = () => {
const filterItem = async (categoryitem) => {
const updateitmes = allModelos.filter((curElm) => {
return curElm.categories === categoryitem
})
getporfolioState(updateitmes)
}
const [getporfolio, getporfolioState] = useState([])
const [allModelos, guardarAllModelo] = useState([]);
$(document).ready(function () {
$(".grid-wrap .grid li").unbind().click(function (e) {
console.log(this.className);
var newe = this.className;
$('.' + newe).addClass('current show');
$("#grid-gallery").addClass("slideshow-open");
});
$("#closeport").unbind().click(function (e) {
$("#grid-gallery").removeClass("slideshow-open");
$(".portfolio .grid li").removeClass('current show');
$(".portfolio .slideshow ul > li").removeClass('current show');
});
});
const portadd = () => {
document.body.classList.add('portfolio');
document.body.classList.add('at-top');
document.getElementById('port').classList.add('no-transform');
document.getElementById('port').classList.add('revealator-within');
document.getElementById('port2').classList.add('no-transform');
document.getElementById('port2').classList.add('revealator-within');
document.getElementById('navbar-collapse-toggle').classList.remove('biohidemenu');
}
const getalldata = async () => {
try {
const res = await fetch("/getdata", {
method: 'Get',
headers: {
'Content-Type': 'application/json'
}
})
const data = await res.json()
// console.log("This is our data load")
// console.log(data.portfolio)
getporfolioState(data.portfolio)
guardarAllModelo(data.portfolio)
} catch (error) {
console.log(error)
// history.push("/backoffice/login")
}
}
useEffect(() => {
getalldata()
portadd()
}, []);
return (
<>
<section id="port" class="title-section text-left text-sm-center revealator-slideup revealator-once revealator-delay1">
<h1 >my <span>portfolio</span></h1>
<span class="title-bg">works</span>
</section>
<section id="port2" className="main-content text-center revealator-slideup revealator-once revealator-delay1">
<div class="container">
<button className="btn btn-about " onClick={() => filterItem('mobileapp')}>Mobile</button>
<button className="btn btn-about " onClick={() => filterItem('frontend')}>Frontend</button>
<button className="btn btn-about " onClick={() => filterItem('gdesign')}>Graphics</button>
</div>
<div id="grid-gallery" className="container grid-gallery">
{/* Portfolio Grid Starts */}
<section className="grid-wrap">
<ul className="row grid">
{
getporfolio.map((getdata, index) => {
return (
<>
<Thumnailport_list
key={index}
portID={getdata._id}
imagetag={getdata.imguploadedFile}
figuertext={getdata.projectname}
/>
</>
)
})
}
</ul>
</section>
{/* Portfolio Grid Ends */}
{/* Portfolio Details Starts */}
<section className="slideshow" id="sdfer">
<ul>
{/* Portfolio Item Detail Starts */}
{
getporfolio.map((getdata, index) => {
return (
<>
<Portlightbox
idlight={getdata._id}
imagelight={getdata.imguploadedFile}
langport={getdata.language}
clientport={getdata.client}
projectnameport={getdata.projectname}
previewport={getdata.preview}
/>
</>
)
})
}
</ul>
{/* Portfolio Navigation Starts */}
<nav>
{/*<span className="icon nav-prev prev"><img src="images/left-arrow.png" alt="previous" /></span>
<span className="icon nav-next next"><img src="images/right-arrow.png" alt="next" /></span>*/}
<span className="nav-close" id="closeport"><img src="images/close-button.png" alt="close" /> </span>
</nav>
{/* Portfolio Navigation Ends */}
</section>
</div>
</section>
</>
)
}
export default Portfolio;