Component with array.map (data) not show in modal pop up - javascript

I have problem, Why the component not show, in modal i want to show many data.
I want to get data from api, and data show in modal when i click.
i create my code like this.
State
const [visible, setVisible] = useState(false);
const toggleVisible = () => {
setVisible(!visible);
};
const [app, setApp] = useState([])
useEffect(() => {
const getApps = async () => {
try {
const response = await
axios.get("http://192.168.20.2:3000/api/V1/application")
setApp(response.data)
} catch (error) {
console.log("Error cannot get api application")
}
}
if (visible) {
getApps()
}
}, [visible])
return value
return (
<div>
<div className="font-sans">
<Modal
open={visible}
onClickBackdrop={toggleVisible}
className="w-11/12 max-w-7xl space-y-10 px-24 pb-20"
>
<Modal.Header>
<div className="grid grid-cols-2">
<div className="grid col-span-1 place-content-start">
<h1 className="text-4xl font-bold">Smart</h1>
</div>
<div className="grid col-span-1 place-content-end">
<Form>
<Input className="rounded-full" bordered type="text" placeholder="Search" />
</Form>
</div>
</div>
</Modal.Header>
<Modal.Body className="space-y-10">
<div className="grid grid-cols-3">
{
app?.map(app => {
<ProductCard
title={app.title}
subTitle={app.subTitle}
/>
})
}
</div>
</Modal.Body>
</Modal>
</div>
</div>
);
but, the component still now show.
i'm use .map, but still now show that component.
thanks before.
Note :
Api : 200 ok

If you are writing it inside a map function, check whether you are returning the modal. return (<Modal></modal/>)

<div className="grid grid-cols-3">
{
apps && apps.map((apps)=>{
return <ProductCard
icon='Icon'
title={apps.title}
subTitle={apps.subTitle}
/>
})
}
or
<div className="grid grid-cols-3">
{
apps && apps.map((apps)=>(
<ProductCard
icon='Icon'
title={apps.title}
subTitle={apps.subTitle}
/>
))
}

Related

How to preserve state of flip card after navigating to another page and then coming back to same page

I tried to preserve the state of flip card, when I flip card I navigated to another route and after coming back from that page the card again come back to its original state, I want to preserve the flipped card state(back side).here is the code first component that renders is Cards and second one is FlippableCard and third one is Cards.
const Cards = () => {
return (
<>
<Navbar></Navbar>
<div className="round-box">Flip a Card</div>
<div className="flex-container">
<Remaincard />
<div className="flex-container-child">
<div className="flex-child">
<FlippableCard title={data[0].cardName} key={0} />
</div>
</div>
</div>
</>
);
};
export default Cards;
function Card({ onClick, title }) {
const navigate = useNavigate();
const timeOutFun = (e) => {
setTimeout(() => navigate("../afterflip/" + title), 300);
console.log(title);
};
return (
<>
<div className="card" onClick={onClick}>
<div className="card-back"></div>
<div className="card-front">
<button
className="middle card-front"
onClick={() => {
timeOutFun();
}}
>
hiii
</button>
<p
onClick={() => {
timeOutFun();
}}
className="text-on-card"
>
{title}
</p>
</div>
</div>
</>
);
}
function FlippableCard({ title, key }) {
const [showFront, setShowFront] = useState(true);
// console.log("showFront");
const [color, setColor] = useState("#110781");
return (
<div className="scroll-remove">
<div className="flippable-card-container">
<CSSTransition in={showFront} timeout={300} classNames="flip">
<Card
title={title}
value={key}
onClick={() => {
setShowFront((v) => !v);
setColor("#A8A8A8");
setShowFront(false);
// getLocalData();
}}
/>
</CSSTransition>
</div>
</div>
);
}
You might want to look into using localStorage.setItem and localStorage.getItem. This will store the data in the browser indefinitely using cache. If you want the data to be deleted or in other words, refreshed, you can use session storage. This retains data until that particular tab is closed.

How can I map different indexes of an array on button click React

I have been trying to find a way so that when I click a button the next movie in the array shows up on the screen. I am new to react so please forgive my code. I think my problem is in how I am fetching data from the external site. I am not sure how/when I should load in the data so that it functions most effeciently. Any help or tips would be greatly appreciated
function App() {
const [items,setItems] = useState([]);
async function getItems() {
const response = await fetch('https://etbd.tech/nuspljr_334360/csv2json.php');
const data = await response.json();
setItems([...data]);
}
useEffect(() => {
getItems();
},[]);
async function loadData() {
const response = await fetch('https://etbd.tech/nuspljr_334360/sread.php?f=imdb_top_1000.csv');
const menu = await response.json();
setItems([...menu]);
}
useEffect(() => {
loadData();
},[]);
function Buttons() {
return (
<div>
<button className="button" onClick={nextMovie}>Next Movie</button>
</div>
)
}
function RenderItem() {
return (
<div>
{items.map((item) => (
<div key={v4()} className='card'>
<section className="description">
<img src={item.Poster_Link} alt="Poster_Image"/>
<section className="title">
<p>{item.Series_Title} ({item.Released_Year})</p>
<p>IMDB Rating: {item.IMDB_Rating}</p>
</section>
<p>{item.Overview}</p>
<p>{item.Genre} - {item.Runtime}</p>
</section>
</div>
))}
</div>
)};
return (
<div className="body">
<h2>Guess that Movie</h2>
<div className="table">
<RenderItem />
<div className="nav">
<Buttons />
</div>
</div>
</div>
);
}
export default App;
Okay, some things missing in your code.
First of all, you are referencing to nextMovie function and did not declare it.
After this, you should think about the logic of your component and how it should behave.
You do have a state for storing your items that you are fetching.
Now you need another state to store some kind of logic to display the current movie and when you click the next movie button, to update this state with the next one.
You can set a const [activeIndex, setActiveIndex] = useState(-1);
When you first fetch your items, you can set movieIndex to 0.
And inside your component render item, you will get rid of the items.map; because you don't want to loop inside your array, you just want to show one.
We are now passing the active movie as a prop to RenderItem component and showing the active movie data.
I recommend that you learn more about javascript before trying react code.
You can see a working demo here: https://codesandbox.io/s/optimistic-sid-8morgf?file=/src/App.js
import React, {useState, useEffect} from 'react'
function App() {
const [items,setItems] = useState([]);
const [activeIndex,setActiveIndex] = useState(-1);
async function getItems() {
const response = await fetch('https://etbd.tech/nuspljr_334360/csv2json.php');
const data = await response.json();
setActiveIndex(0);
setItems([...data]);
}
useEffect(() => {
getItems();
},[]);
function Buttons() {
return (
<div>
<button className="button" onClick={nextMovie}>Next Movie - next index {activeIndex + 1}</button>
</div>
)
}
function RenderItem({item}) {
return (
<div>
<div className='card'>
<section className="description">
<img src={item.Poster_Link} alt="Poster_Image" />
<section className="title">
<p>{item.Series_Title} ({item.Released_Year})</p>
<p>IMDB Rating: {item.IMDB_Rating}</p>
</section>
<p>{item.Overview}</p>
<p>{item.Genre} - {item.Runtime}</p>
</section>
</div>
</div>
)};
const nextMovie = () => setActiveIndex((prev) => prev + 1);
return (
<div className="body">
<h2>Guess that Movie</h2>
<div className="table">
{items.length === 0 ? 'Loading...' : (<>
<RenderItem item={items[activeIndex]} />
<div className="nav">
<Buttons />
</div>
</>)}
</div>
</div>
);
}
export default App;

React Uncaught TypeError: myarray.map is not a function

I keep getting this error - Uncaught TypeError: itemList.map is not a function
I was under the impression itemList was just supposed to be an array? There is an array being returned in console log for itemList.
The following code is just a popup modal that pulls in data from a users shopping cart.
function Example(props) {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const [itemList, setItemList] = useState('');
const url = wordpressurl + "checkout/";
useEffect(() => {
async function getItems() {
const value = await localforage.getItem('cart_key');
await CoCart.get("cart?cart_key=" + value).then((response) => {
setItemList(response.data.items);
})
}
console.info(itemList);
if (!itemList) {
getItems();
}
});
return (
<>
<div onClick={handleShow} className='cartlable'>Cart</div><div id="cartcount"><div className="cartcount">0</div></div>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton className="me-2">
<Modal.Title>Your Cart</Modal.Title>
</Modal.Header>
<Modal.Body id="cartlist">
<div className="container-fluid">
<div className="row">
<div className="col-8 text-start"><h5>ITEM</h5></div>
<div className="col-1 text-center"><h5>QTY</h5></div>
<div className="col-2 text-end"><h5>SUBTOTAL</h5></div>
<div className="col-1 text-end pe-2"></div>
</div>
{itemList.map((cartitem) =>
<div className="row align-middle cartitemrows">
<div className="col-1 text-start"><img src={cartitem.featured_image} className="cartimage" alt="" />{cartitem}</div>
</div>
)}
<div className="row pt-3"><div className="col-11 text-end"><h5>TOTAL : <span id="carttotal"></span></h5></div></div>
<form id="form-id" action={url} method="get" encType="multipart/form-data">
<input type="hidden" name="cocart-load-cart" />
<button id="your-id">Checkout</button>
</form>
</div>
</Modal.Body>
<Modal.Footer>
</Modal.Footer>
</Modal>
</>
);
}
Does anyone know where I'm going wrong? Thanks
Btw this is what shows up in console if I declare the useState as a string instead of an array like so const [itemList, setItemList] = useState([]); -
(2) [{…}, {…}]
0: {item_key: '698d51a19d8a121ce581499d7b701668', id: 111, name: 'Cuff Beanie', title: 'Cuff Beanie', price: '3000', …}
1: {item_key: '7ce9004ae3ad190443d43d7f81241060', id: 107, name: 'Womans T-shirt - MED Womens', title: 'Womans T-shirt', price: '6000', …}
length: 2
[[Prototype]]: Array(0)
You're setting the default state of your list to an empty string.
Use
const [itemList, setItemList] = useState([]);
to set the state to an empty array.
String objects do not have a map function.
Array objects(even empty ones) do have the map function
Also make sure that your response from the server is an array
In your code you are defining the value of const [itemList, setItemList] = useState(''); as an empty string and map is an array method so insted of an empty string you can use an empty array.
const [itemList, setItemList] = useState([]);
I was going about trying to populate the contents of a users shopping cart the wrong way, for example I didn't even need useEffect. So I restructured it completely and ended up with this -
import React, {useState} from 'react';
import Modal from 'react-bootstrap/Modal';
import CoCartAPI from "#cocart/cocart-rest-api";
import localforage from "localforage";
import 'bootstrap-icons/font/bootstrap-icons.css';
const wordpressurl = "http://localhost/wordpress/";
const CoCart = new CoCartAPI({
url: wordpressurl,
});
function Example(props) {
const [show, setShow] = useState(false);
const [itemList, setItemList] = useState([]);
const [cartKey, setCartKey] = useState('');
const [cartTotal, setCartTotal] = useState('');
const handleClose = () => setShow(false);
const url = wordpressurl + "checkout/";
async function getItems() {
setShow(true);
const value = await localforage.getItem('cart_key');
setCartKey(value);
await CoCart.get("cart?cart_key=" + value).then((response) => {
var carttotal = response.data.totals.subtotal / 100;
const result = response.data.items;
setItemList(result);
setCartTotal(carttotal);
})
}
return (
<>
<div onClick={() => getItems()} className='cartlable'>Cart</div><div id="cartcount"><div className="cartcount">0</div></div>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton className="me-2">
<Modal.Title>Your Cart</Modal.Title>
</Modal.Header>
<Modal.Body id="cartlist">
<div className="container-fluid">
<div className="row">
<div className="col-8 text-start"><h5>ITEM</h5></div>
<div className="col-1 text-center"><h5>QTY</h5></div>
<div className="col-2 text-end"><h5>SUBTOTAL</h5></div>
<div className="col-1 text-end pe-2"></div>
</div>
{itemList.map(({ id, featured_image, name, value, quantity, totals, item_key }) => (
<div key={id} className="row align-middle cartitemrows">
<div className="col-1 text-start"><img src={featured_image} className="cartimage" alt="" /></div>
<div className="col-7 text-start">{name}</div>
<div className="col-1 text-center">{quantity.value}</div>
<div className="col-2 text-end">{totals.total}</div>
<div className="col-1 text-end pe-2"><i className="bi bi-trash" onClick={() => removeProduct(item_key, value)}></i></div>
</div>
))}
<div className="row pt-3"><div className="col-11 text-end"><h5>TOTAL : <span id="carttotal">{cartTotal}</span></h5></div></div>
<form id="form-id" action={url} method="get" encType="multipart/form-data">
<input type="hidden" name="cocart-load-cart" value={cartKey} />
<button id="your-id">Checkout</button>
</form>
</div>
</Modal.Body>
<Modal.Footer>
</Modal.Footer>
</Modal>
</>
);
}
async function removeProduct(productkey) {
await CoCart.delete('cart/item/<' + productkey + '>')
.then((response) => {
console.log("Response Status:", response.status);
console.log("Response Headers:", response.headers);
console.log("Response Data:", response.data);
});
}
export default Example
No doubt there could be a few improvements that could be made but as is it works perfectly

OnClick event results differently in form and image

I have a navbar component with a search bar and the main page component. When an npm package name is inputted in the search bar it should render the main page component with the details of the package using api.npms.io.
App.jsx
function App() {
const [input, setInput] = useState('react');
return (
<div className="App">
<Navbar setInput={setInput} />
<div className="sections">
<Main input={input} />
</div>
</div>
);
}
export default App;
navbar
function Navbar({ setInput }) {
const inputRef = useRef();
const submitHandler = () => {
setInput(inputRef.current.value);
inputRef.current.value = '';
};
return (
<div className="Navbar" id="Navbar">
<div className="logo">
<img src={logo} alt="logo" />
</div>
<div className="line"></div>
<form onSubmit={submitHandler}>
<div className="search">
<img src={search} alt="search" onClick={submitHandler} />
<input
placeholder={'Search for a NPM package'}
name="name"
type="text"
ref={inputRef}
id="name"
></input>
</div>
</form>
</div>
);
}
export default Navbar;
Main.jsx
function Main({ input }) {
const [packageInfo, setPackageInfo] = useState(null);
const [loading, setLoading] = useState(true);
const fetchPackageInfo = async (input) => {
const response = await fetch(`https://api.npms.io/v2/package/${input}`);
const data = await response.json();
setPackageInfo(data);
setLoading(false);
};
useEffect(() => {
fetchPackageInfo(input);
}, [input]);
return (
<div>
{loading ? (
<Loader />
) : (
<div className="Main" id="Main">
<div className="row">
<Summary
heading={packageInfo.collected.metadata.name}
version={packageInfo.collected.metadata.version}
description={packageInfo.collected.metadata.description}
license={packageInfo.collected.metadata.license}
npm={packageInfo.collected.metadata.links.npm}
github={packageInfo.collected.metadata.links.homepage}
downloads={Math.trunc(
packageInfo.evaluation.popularity.downloadsCount
).toLocaleString()}
keywords={packageInfo.collected.metadata.keywords.join(', ')}
/>
</div>
</div>
)}
</div>
);
}
export default Main;
When I input the value in the search bar and then click on the image or the search icon, it gives me the expected output which is to render the details of the package but while the data is being fetched from the API it does not show the loader.
The next problem is when I submit the inputted value it renders the details of the default package which is react and not the package name entered in the search bar.
Any help would be beneficial. Also, I am new to React and am not sure if I am managing state the right way.
I fixed the problem by adding setLoading(true) before fetching the API and also by adding e.preventDefault() in the submitHandler() function

implementing local storage in react application

I am creating a challenge tracking app in React. I would like to, after clicking on the challenge button and approving it, be able to add it and save it to the local storage (as a value to save the name of the chosen challenge) and later to print it in the dashboard.
Could anyone please help me with that.
I have 3 classes I am working now and will paste them below.
ChooseChallenge.js
function Challange() {
const [isPopped, setPop] = useState(false);
const pop = () => {
setPop(!isPopped);
};
return (
//Fragments
<>
{isPopped && <Dialog />}
<div className="chooseChallenge">
{/* <Leaf/> */}
<h1 className="newchallenge">New Challange</h1>
<hr />
<div className="challanges">
<button className="challangeBtn" onClick={pop}>
Eat Vegetarian (31days)
</button>
<button className="challangeBtn" onClick={pop}>
Take the bike to work (14days)
</button>
<button className="challangeBtn" onClick={pop}>
Recycle your plastic bottles (31days)
</button>
<button className="challangeBtn" onClick={pop} >
Use public transport to commute (31days)
</button>
<button className="challangeBtn" onClick={pop}>
Don't fly an airplane (365days)
</button>
</div>
<br />
</div>
</>
);
}
export default Challange;
Dialog.js
function Dialog (){
const [isOpen, setOpennes] = useState(true);
const Close = () => {
setOpennes(false);
}
const [value, setValue] = React.useState(
localStorage.getItem('challengeName') || ''
);
React.useEffect(() => {
localStorage.setItem('challengeName', value);
}, [value]);
const onChange = event => setValue(event.target.value);
return(
<div className={isOpen ? 'dialogBox' : 'dialogHide'}>
<h3 id="header">Do you accept the challange?</h3>
<div className="approvalButtons">
<button className= "approvalButton" onClick = {Close} value={value} onChange={onChange}> Approve </button>
<button className= "approvalButton" onClick = {Close}> Decline </button>
</div>
</div>
)
}
export default Dialog;
Dashboard.js
export default function Dashboard() {
// const challengelist = document.querySelector('#challange-list')
const [challs, setChalls] = useState([]);
useEffect(() => {
const fetchData = async () => {
var challs = [];
await database
.collection("Challenges")
.get()
.then((snapshot) => {
snapshot.docs.forEach((doc) => {
challs.push(doc.data().ChallengeName);
});
});
setChalls(challs);
};
fetchData();
}, []);
return (
<div className="Dashboard">
<Header />
<div className="circle">
<img id="leafpicture" src={leafpic} alt="eco-picture" />
<div className="textIn">
<h1> You saved </h1>
<h5>0.00 CO2</h5>
</div>
</div>
<div>
<ul id="challange-list">
{challs.map((ch) => (
<li key={ch}>{ch}</li>
))}
</ul>
</div>
<div className="progressbar">
<h3>Track your challenges!</h3>
{testData.map((item, idx) => (
<ProgressBar
key={idx}
bgcolor={item.bgcolor}
completed={item.completed}
/>
))}
</div>
<br />
</div>
);
}
on dialog.js the value of the button starts with an empty string and this value never changes, so you are always storing and empty string.

Categories