if i click button then show this button id in reactJs - javascript

i create a onclick function const showContent=(id)=>{} and if i click the perticular button they will show id in const showContent = (id)=>{console.log(id)} like this .....
inside thisCart.jsx i rendering CartStyle.jsx using map method so this delete button inside here.
Cart
function Cart() {
const [data, setData] = useState([])
useEffect(() => {
const data = JSON.parse(localStorage.getItem('Cart'));
data.map(async (v) => {
try {
axios.get(`/cart/${v}`)
.then((res) => {
return setData((preV) => {
return [...preV, res.data]
})
})
.catch(e => { console.log(e) })
} catch (e) {
console.log(e);
}
})
}, [])
const showContent=(id)=>{
console.log('this is id', id)
}
return (
<>
<div className=" cartStyle row g-3">
<div className="left col-md-4">
<button className="btn btn-primary">Proceed to Buy</button>
</div>
</div>
<div className="right col-md-8 flex flex-wrap justify-around">
{
data.map((v, i) => {
return <CartStyle
key={i}
id={i}
title={v.title}
price={v.DiscountPrice}
img={v.image}
delete={showContent(i)}
/>
})
}
</div>
</div>
</>
)
}
export { Profile, Cart };
CartStyle
this is a CartStyle means i'm passing data from Cart.jsx to CarStyle.jsx using props
const CartStyle= (props) => {
return (
<>
<div style={{ width: '22em', height: '10em'}} className=" p-2 row g-3 card container rounded-2xl shadow py-2 my-3">
<button id="delBtn" onClick={props.delete} className="btn btn-primary my-2">Delete</button>
</div>
</div>
</>
)
};
export default CartStyle;

<CartStyle
key={i}
id={i}
title={v.title}
price={v.DiscountPrice}
img={v.image}
delete={(i) => showContent(i)} // or delete={showContent}
/>
// CartStyle
<button id="delBtn" onClick={() => props.delete(props.id)} className="btn btn-primary my-2">Delete</button>

You pass your id on your parent compoenent.Then you get the id in your child component as props.
const CartStyle= (props) => {
return (
<>
<div style={{ width: '22em', height: '10em'}} className=" p-2 row g-3
card container rounded-2xl shadow py-2 my-3">
<button id="delBtn" onClick={() => props.delete(props.id)}
className="btn btn-primary my-2">Delete</button>
</div>
</>
)
};
export default CartStyle

You need to assign a function to delete prop instead of invoking it directly.
Replace
<CartStyle
delete={showContent(i)}
/>
with
<CartStyle
delete={() => showContent(i)}
/>

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.

Make div with react components as children disappear if I click outside of it

I want to make a form that disappears if I click outside of it.
Form Component:
const CreateTaskPopup = (props) => {
const ref = query(collection(db, "tasks"));
const mutation = useFirestoreCollectionMutation(ref);
useEffect(() => {
const closeTaskPopup = (event) => {
if (event.target.id != "addForm") {
props.setTrigger(false)
}
}
document.addEventListener('click', closeTaskPopup);
return () => document.removeEventListener('click', closeTaskPopup)
}, [])
return (props.trigger) ? (
<>
<div className="bg-darkishGrey my-4 p-1 mx-3 ml-16 cursor-pointer block"
id="addForm">
<div className="flex justify-between">
<div className="flex break-all items-center ">
<Image src={fileIcon} className="w-6 mx-2"/>
<div>
<Formik
initialValues={{
taskName: "",
taskIsDone: false,
parentId: props.parentId ? props.parentId : "",
hasChildren: false,
}}
onSubmit={(values) => {
mutation.mutate(values);
props.setTrigger(false);
}}
>
<Form>
<div className="">
<TextInput
placeholder="Type a name"
name="taskName"
type="text"
/>
</div>
</Form>
</Formik>
</div>
</div>
<div className="flex items-center">
</div>
</div>
</div>
</>
) : null
}
export default CreateTaskPopup
Text Input Component:
import { useField } from "formik";
const TextInput = ({ label, ...props}) => {
const [field, meta] = useField(props);
return (
<div>
<label id="addForm" className="text-lightestGrey text-xl block"
htmlFor={props.id || props.name}>
{label}
</label>
<input id="addForm" className="bg-darkishGrey text-xl text-almostWhite my-2
outline-none w-10/12 rounded-sm p-1 mx-3" {...field} {...props} />
{meta.touched && meta.error ? <div>{meta.error}</div>: null}
</div>
);
};
export default TextInput;
I tried giving an id to the elements inside it but it's not the best solution as it has components from the Formik library to which I can't assign an id. I don't know what would be the best solution for this problem.

How to access function component's state variables in ReactJS?

I've been developing a website and I'm faced with an issue about accessing state varibles to a component. I've a address page(Addresses.jsx file) which has address modal. I'm also have a component which contains address modal's content (Address.jsx). I would like to access state inside Address.jsx file. How can I do that? If you can help me. I would be very appreciate.
Here is my code blocks;
Address.jsx file;
const Addresses = () => {
const [selectedAddress, setSelectedAddress] = useState();
const [modalType, setModalType] = useState();
const {
elementRef: addressModalRef,
show: showAddressModal,
hide: hideAddressModal,
} = useModal();
return (
<>
<div className="bg-light px-3 px-lg-4 py-4">
<h1 className="h4 mb-4">My Addresses</h1>
<div className="row g-3">
<div className="col-12 col-md-6 col-lg-4">
<AddressButton
onClick={() => {
setSelectedAddress(undefined);
setModalType("NewAddress");
showAddressModal();
}}
/>
</div>
{ADDRESSES.map((address, i) => (
<div className="col-12 col-md-6 col-lg-4" key={i}>
<AddressButton
{...address}
onClick={() => {
setSelectedAddress(address);
setModalType("EditAddress");
showAddressModal();
}}
/>
</div>
))}
</div>
</div>
<AddressModal
address={selectedAddress}
elementRef={addressModalRef}
hide={hideAddressModal}
modalType={modalType}
/>
</>)};
export default Addresses;
Address Modal file;
const AddressModal = ({ address, elementRef, hide, modalType }) => {
const onSaveAddress = () => {
console.log(address);
hide();
};
return (
<Modal elementRef={elementRef} centered size="lg" fullscreen>
<ModalBody>
<AddressForm address={address} /> // I would like to get this component's state in onSaveAddress funtion
</ModalBody>
<ModalFooter>
<button
type="button"
className="btn btn-primary flex-grow-1 px-5"
onClick={onSaveAddress}>
Kaydet
</button>
</ModalFooter>
</Modal>)};
export default AddressModal;
Instead of accessing child components state, which is not possible, do the following
Address Model
<AddressForm
address={address}
onSave={onSaveAddress}
/>
Address Form
const AddressForm = ({ onSave }) => {
const handleFormSubmit = () => {
onSave(formData);
};
return (
<form onSubmit={handleFormSubmit}>
</form>
);
}
Then in onSaveAddress, you will have access to the form data.

".map is not a function" error in react.js

I have developed a basic todo app using react-dnd. I am trying to get the details from the database and store it in the state. And by using the state I want to map the values retrieieved from the database.
I tried looking into the output using console.log statement, and it was something like this.
However when I try to use the map function like this:
{state.map((item, index) => (
<Draggable
key={item._id}
draggableId={item._id + ""}
index={index}
>
{console.log(item._id, "KEY")}
{(provided) => (
<li
className="list-group-item d-flex justify-content-between align-items-start align-items-center"
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<div className="ms-2 me-auto">
<span className="ml-3 mr-2">
<input
type="checkbox"
className="form-check-input"
id={index}
value={index}
checked={item.selected}
onChange={(e) => {
const target = e.target.value;
const val = state[target].selected;
// console.log(val);
let tmp = Array.from(state);
tmp[target].selected = !val;
// console.log(tmp[target]);
setState(tmp);
// console.log(state);
}}
/>
</span>
<span className="font-weight-bold">{item.title}</span>
</div>
<span>
{/* <i className="bi bi-trash text-danger" /> */}
<button
className="btn btn-sm"
onClick={(e) => {
e.preventDefault();
handleDelete(item._id, index);
}}
>
<i className="bi bi-trash text-danger" />
</button>
</span>
</li>
)}
</Draggable>
Its showing an error as "state.map" is not a function
However I also tried using "state.stage.map()" . Afterwards its showing an error as state.stage is undefined. Is there any proper way of using this .map function?
I have attached the full code here below.
function ProjectsDashboard() {
useEffect(() => {
preload();
}, []);
const [state, setState] = useState([]);
const [todo, setTodo] = useState("");
const [loading, setLoading] = useState(false);
const preload = async () => {
setLoading(true);
try {
const res = await axios.get("/stages");
setState(res.data);
console.log(state, "STATE")
console.log(res.data,"DATA")
setLoading(false);
} catch (error) {
alert("Couldn't find any Todos! ");
setLoading(false);
}
};
console.log(state, "STATE")
const lists = () => (
<div className="row">
<div className="col-sm-12 col-md-4 offset-md-2 col-lg-4 offset-lg-2 border border-danger p-4">
<h3 className="text-center mb-4">Draggable List</h3>
<DragDropContext onDragEnd={handleDragEnd}>
<Droppable droppableId="todos">
{(provided) => (
<ul
className="list-group"
{...provided.droppableProps}
ref={provided.innerRef}
>
{state.stage.map((item, index) => (
<Draggable
key={item._id}
draggableId={item._id + ""}
index={index}
>
{console.log(item._id, "KEY")}
{(provided) => (
<li
className="list-group-item d-flex justify-content-between align-items-start align-items-center"
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<div className="ms-2 me-auto">
<span className="ml-3 mr-2">
<input
type="checkbox"
className="form-check-input"
id={index}
value={index}
checked={item.selected}
onChange={(e) => {
const target = e.target.value;
const val = state[target].selected;
// console.log(val);
let tmp = Array.from(state);
tmp[target].selected = !val;
// console.log(tmp[target]);
setState(tmp);
// console.log(state);
}}
/>
</span>
<span className="font-weight-bold">{item.title}</span>
</div>
<span>
{/* <i className="bi bi-trash text-danger" /> */}
<button
className="btn btn-sm"
onClick={(e) => {
e.preventDefault();
handleDelete(item._id, index);
}}
>
<i className="bi bi-trash text-danger" />
</button>
</span>
</li>
)}
</Draggable>
))}
{provided.placeholder}
</ul>
)}
</Droppable>
</DragDropContext>
</div>
<div
className="col-sm-12 col-md-4 col-lg-4 border border-info p-4"
style={{ marginLeft: "10px" }}
>
<h3 className="text-center mb-4">NON-Draggable List</h3>
<ul className="list-group">
{state.map(
(item, index) =>
item.selected && (
<li className="list-group-item" key={index}>
{item.title}
</li>
)
)}
</ul>
</div>
</div>
);
const handleDragEnd = (result) => {
// console.log(result);
if (!result.destination) return;
const items = Array.from(state);
const [recordedItem] = items.splice(result.source.index, 1);
items.splice(result.destination.index, 0, recordedItem);
setState(items);
// console.log(state);
};
const handleDelete = async (id, index) => {
try {
await axios.delete(`/api/todo/${id}`);
// preload();
const temp = Array.from(state);
temp.splice(index, 1);
setState(temp);
} catch (error) {
if (`Error! ${error.response.data.err}`) {
alert(error.response.data.err);
} else {
alert(`Error ${error.response.status}: ${error.response.statusText}`);
}
}
};
const addNewTodoForm = () => (
<div className="row">
<div className="col-md-8 offset-md-2 mb-4 form-group">
<label htmlFor="newtodo">Add a New Todo Item</label>
<input
type="text"
className="form-control"
name="newtodo"
id="newtodo"
value={todo}
placeholder="Add New Todo"
required
onChange={handleChange}
/>
<button
className="btn btn-block btn-outline-primary mt-2"
onClick={handleSubmit}
>
Submit
</button>
</div>
</div>
);
const handleChange = (e) => {
e.preventDefault();
setTodo(e.target.value);
};
const handleSubmit = async (e) => {
e.preventDefault();
if (todo === "" || todo === null) {
alert(
"To add a New Todo item, please fill out the 'Add New Todo' field."
);
return;
}
const temp = {
title: todo,
};
try {
const res = await axios.post("/api/todo", temp);
setTodo("");
const tmp = Array.from(state);
tmp.push(res.data);
setState(tmp);
// preload();
} catch (error) {
if (error.response.data && error.response.data.err) {
alert(`Error! ${error.response.data.err}`);
} else {
console.log(error);
alert(`Error ${error.response.status}: ${error.response.statusText}`);
}
}
};
return (
<>
<div className="container">
<h1 className="text-center m-4 font-weight-bold text-uppercase">
DRAG TO DO{" "}
<span className="text-lowercase font-weight-normal">V1.0.1</span>
</h1>
{/* {addNewTodoForm()}*/}
{lists() }
</div>
</>
);
};
export default ProjectsDashboard;
Try this
{state.stage && state.stage.map(.........
This is because upon first render, state is initialized as an empty array. You could either initialize state as:
const [state, setState] = useState({ stage: [] });
Or write a conditional check before calling lists()
{state && state.stage ? lists() : null}

How to get clicked element datas inside React Bootstrap Modal?

I have a problem with getting the current clicked element's data's from the API and displaying it inside React Bootstrap Modal body. The parent component is TopMovies.js which looks like:
import React, { useState } from 'react';
import TopMoviesModal from '../top-movies-modal/TopMoviesModal';
const TopMovies = ({ currentMovies }) => {
const [isOpen, setIsOpen] = useState(false);
const showModal = () => {
setIsOpen(true);
};
const hideModal = () => {
setIsOpen(false);
};
const renderMovies = () => {
if (Object.keys(currentMovies).length && currentMovies.length) {
return (
<div className="movies-labels-container">
{currentMovies.map((movie) => {
return (
<div className="movie-label"
key={movie.id.attributes['im:id']} title={movie['im:name']['label']}
onClick={showModal}>
<img className="movie-img" src={movie['im:image'][2]['label']} alt={movie['im:name']['label']} />
<br />
<div className="text-under">
<span id="movie-title">{movie['im:name']['label']}</span>
<br />
<span id="movie-subtitle">{movie.category.attributes.term}</span>
</div>
</div>
);
})}
</div>
);
}
};
return (
<section className="top-movies-list">
<div className="container-outter">
<div className="container-fluid">
<div className="row">
<div className="col-lg-12 col-md-12 col-sm-12" id="top-movies-module">
<div className="top-movies-container">
<h1 className="container-title">
TOP 100 movies
</h1>
{renderMovies()}
<TopMoviesModal
currentMovies={currentMovies}
hideModal={hideModal}
isOpen={isOpen} />
</div>
</div>
</div>
</div>
</div>
</section >
)}
export default TopMovies;
and the child component TopMoviesModal.js which looks like this:
import React from 'react';
import Modal from "react-bootstrap/Modal";
import Button from "react-bootstrap/Button";
const TopMoviesModal = ({ currentMovies, hideModal, isOpen }) => {
const renderMoviesDetails = () => {
if (Object.keys(currentMovies).length && currentMovies.length) {
return (
<div>
{currentMovies.map((movie, index) => {
return (
<div className="movie-label" key={movie.id.attributes['im:id']}>
<span id="movie-title">{movie['im:name']['label']}</span>
</div>
);
})}
</div>
);
}
};
return (
<Modal
show={isOpen}
onHide={hideModal}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
Modal heading
</Modal.Title>
</Modal.Header>
<Modal.Body>
{renderMoviesDetails()}
</Modal.Body>
<Modal.Footer>
<Button onClick={hideModal}>Close</Button>
</Modal.Footer>
</Modal>
);}
export default TopMoviesModal;
Could you help me to solve this problem? I would be very grateful, thanks a lot

Categories