Reordered array not getting displayed in the web - react-beautiful-dnd - javascript

I have developed a simple todo app using react-beautiful-dnd. I am able to retrieve data from the database and display it in the list. However, when I try to drag and rearrange the order, the reordered array is getting printed in the console (I tried testing using console.log), however the new reorderd array is not getting displayed in the interface. I am very new to this MERN stack, therefore I am unable to find the reason for this error.
I have attached screenshots of the output before and after dragging an element, and also the console log output.
before drag-and-drop
after drag and drop
console-log array order before drag and drop
console-log reordered array
The code :
function ProjectsDashboard() {
useEffect(() => {
preload();
}, []);
const [state, setState] = useState([]);
const[stage,setStage] = 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);
}
};
var formattedArray =state.stage && state.stage.map(item => Object.keys(item).map(i => item[i]));
console.log(formattedArray, "FORMATTED ARRAY")
// setState( formattedArray);
// 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}
>
{console.log("HELLO-out")}
{state.stage && state.stage.map((item, index) => (
<Draggable
key={item._id}
draggableId={item._id + ""}
index={index}
>
{(provided) => (
<li
className="list-group-item d-flex justify-content-between align-items-start align-items-center"
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
{console.log("HELLO")}
<div className="ms-2 me-auto">
<span className="font-weight-bold">{item.stageName}</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.stage && state.stage.map(
(item, index) =>
item.selected && (
<li className="list-group-item" key={index}>
{item.title}
</li>
)
)}
</ul>
</div>
</div>
);
const handleDragEnd = (result) => {
console.log(result.destination,"DESTI");
if (!result.destination) return;
const items = Array.from(state.stage);
console.log(items,"ITEMS-DRAG")
console.log(result.source.index,"SOURCE INDEX")
console.log(result.destination.index,"DESTINATION INDEX")
const [recordedItem] = items.splice(result.source.index, 1);
console.log(recordedItem,"RECORDED")
items.splice(result.destination.index, 0, recordedItem);
console.log(items, "NEW ITEM")
setState(items);
console.log(state, "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;

Related

react-paypal-js not changing currency

function App() {
return (
<PayPalScriptProvider
options={{
"client-id": process.env.REACT_APP_PAYPAL_CLIENT_ID,
currency: "PHP",
}}
>
<Router>
<div className="app">
<Routes>
<Route path="/" element={<LandingPage />}></Route>
<Route path="/admin" element={<Admin />}></Route>
</Routes>
</div>
</Router>
</PayPalScriptProvider>
);
}
I specified the currency in the properties of paypal script provider but it's still in usd
Purchase Image showing USD
What should I do to change the currency of it to Philippine Peso
Here is the link of the npm package that i used:
https://www.npmjs.com/package/#paypal/react-paypal-js
Whole Code
import "./App.css";
import { useState, useRef, useEffect } from "react";
import Dropzone from "react-dropzone";
import { PayPalButtons, PayPalScriptProvider } from "#paypal/react-paypal-js";
import {
arrayUnion,
collection,
deleteDoc,
doc,
onSnapshot,
orderBy,
query,
serverTimestamp,
setDoc,
updateDoc,
} from "firebase/firestore";
import { db, storage } from "./firebase.js";
import { v4 as uuidv4 } from "uuid";
import { getDownloadURL, ref, uploadString } from "firebase/storage";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import thanks from "./Images/thanks.png";
function PaypalCheckoutButton(props) {
const [error, setError] = useState(null);
const handleApprove = (orderID) => {
props.completeOrder();
};
if (error) {
alert(error);
}
return (
<div style={{ marginTop: "1rem" }}>
<PayPalButtons
createOrder={(data, actions) => {
return actions.order.create({
purchase_units: [
{
description: props.product.description,
amount: {
currency_code: "PHP",
value: props.product.price,
},
},
],
});
}}
onApprove={async (data, action) => {
const order = await action.order.capture();
console.log("order", order);
handleApprove(data.orderID);
}}
onCancel={() => {}}
onError={(err) => {
setError(err);
console.log("Paypal Checkout Error", err);
}}
/>
</div>
);
}
function Step1(props) {
const [isGift, setIsGift] = useState(null);
const [message, setMessage] = useState("");
function newKeychain() {
setIsGift(null);
props.setOrders((currentOrders) => [
{ image: props.image, message: message },
...currentOrders,
]);
props.setImage(null);
}
function handleShowButton() {
if (isGift === false) {
return props.image;
} else if (isGift === true) {
return props.image && message !== "";
}
}
return (
<div
className="step1 step"
style={isGift === true ? { marginTop: "5rem" } : {}}
>
{isGift === null && (
<>
<h1 className="title">Choose what type of keychain</h1>
<div className="purchaseTypeSection">
<div
className="formyself purchaseType"
onClick={() => setIsGift(false)}
>
<h2>Standard</h2>
<p className="keychainTypeDescription">
Perfect for personal use
</p>
<h2 className="price">₱69</h2>
</div>
<div className="gift purchaseType" onClick={() => setIsGift(true)}>
<h2>With Message</h2>
<p className="keychainTypeDescription">
Perfect for gifts to your love ones
</p>
<h2 className="price">₱99</h2>
</div>
</div>
</>
)}
{isGift !== null && (
<>
<h1 className="title">Choose your image</h1>
<Dropzone
onDrop={(acceptedFiles) =>
props.setImage(() => {
if (!acceptedFiles[0]) {
return null;
}
var fr = new FileReader();
fr.onload = function () {
props.setImage(fr.result);
};
fr.readAsDataURL(acceptedFiles[0]);
})
}
multiple={false}
accept={{ "image/jpeg": [".png", ".jpg"] }}
>
{({ getRootProps, getInputProps }) => (
<section>
<div
{...getRootProps()}
style={props.image ? { padding: "0 !important" } : {}}
>
<input {...getInputProps()} />
{props.image ? (
<img
className="drop__image"
src={props.image}
alt="Your Keychain"
/>
) : (
<h3 className="drop__text">
Drag your image here, or click to select a file
</h3>
)}
</div>
</section>
)}
</Dropzone>
{isGift === true && (
<textarea
className="messageInput largeInput"
maxLength={100}
placeholder="Enter your message to your special someone here"
value={message}
onChange={(e) => setMessage(e.target.value)}
></textarea>
)}
<div className="step1Buttons">
<button
className="step1Button"
onClick={() => {
setIsGift(null);
props.setImage(null);
}}
>
Go back
</button>
{handleShowButton() && (
<>
<button className="step1Button" onClick={newKeychain}>
Create Another Keychain
</button>
<button
className="step1Button"
onClick={() => {
newKeychain();
props.setStep((step) => step + 1);
}}
>
Next
</button>
</>
)}
</div>
</>
)}
</div>
);
}
function Step2(props) {
function completed() {
return (
props.customerName !== "" &&
props.customerNumber > 0 &&
props.customerAddress !== ""
);
}
return (
<div className="step2 step center">
<div className="question center">
<h3>Let us know who will we deliver it to</h3>
<input
placeholder="Enter your name"
value={props.customerName}
onChange={(e) => props.setCustomerName(e.target.value)}
></input>
</div>
<div className="question center">
<h3>For us to give you infomations about the delivery and package</h3>
<input
type="number"
placeholder="Enter your phone number"
value={props.customerNumber}
onChange={(e) => props.setCustomerNumber(e.target.value)}
></input>
</div>
<div className="question center">
<h3>Let us know where to deliver</h3>
<textarea
className="largeInput locationInput"
placeholder="Enter your location"
value={props.customerAddress}
onChange={(e) => props.setCustomerAddress(e.target.value)}
></textarea>
</div>
<div className="step1Buttons">
<button
className="step1Button createAnother"
onClick={() => props.setStep((step) => step - 1)}
>
Go Back
</button>
<button
className="step1Button"
style={
completed()
? { backgroundColor: "#5c90a0", cursor: "pointer" }
: { backgroundColor: "#b5b5b5", cursor: "default" }
}
onClick={() => {
if (!completed()) {
return;
}
props.setStep((step) => step + 1);
}}
>
Next
</button>
</div>
</div>
);
}
function Step3(props) {
function getPrice() {
var p = 0;
props.orders.forEach((o) => {
if (o.message === "") {
p += 69;
} else {
p += 99;
}
});
return p;
}
function getDescription() {
var giftCount = 0;
var standardCount = 0;
props.orders.forEach((o) => {
if (o.message === "") {
standardCount += 1;
} else {
giftCount += 1;
}
});
return `${giftCount > 0 ? `${giftCount} Gift Keychain/s` : ""}${
giftCount * standardCount !== 0 ? " and " : ""
}${standardCount > 0 ? `${standardCount} Standard Keychain/s` : ""}`;
}
async function completeOrder(method) {
// get the order informations
// add it to the orders collection in firebase
const orderId = uuidv4();
await setDoc(doc(db, "orders", orderId), {
customerName: props.customerName,
customerNumber: props.customerNumber,
customerAddress: props.customerAddress,
timestamp: serverTimestamp(),
paymentMethod: method,
description: getDescription(),
price: getPrice(),
status: "toApprove",
});
for (let i = 0; i < props.orders.length; i++) {
let order = props.orders[i];
const fileRef = ref(storage, `orders/${orderId}`);
await uploadString(fileRef, order.image, "data_url").then(
async (snapshot) => {
const downloadUrl = await getDownloadURL(fileRef);
updateDoc(doc(db, "orders", orderId), {
orders: arrayUnion({
keychainImage: downloadUrl,
keychainMessage: order.message,
}),
});
}
);
}
props.setHasOrdered(true);
props.setOrders([]);
props.setCustomerName("");
props.setCustomerAddress("");
props.setCustomerNumber("");
props.setStep(1);
}
return (
<div className="step3 step">
<button
className="paymentMethod cod"
onClick={() => completeOrder("Cash On Delivery")}
>
Cash on Delivery
</button>
<h2 style={{ marginTop: "1rem" }}>Or</h2>
<PaypalCheckoutButton
completeOrder={() => completeOrder("Online")}
product={{ description: getDescription(), price: getPrice() }}
/>
</div>
);
}
function LandingPage(props) {
const [orders, setOrders] = useState([]);
const [customerName, setCustomerName] = useState("");
const [customerNumber, setCustomerNumber] = useState();
const [customerAddress, setCustomerAddress] = useState("");
const [step, setStep] = useState(1);
const [navbar, setNavbar] = useState(false);
const bottomRef = useRef();
const topRef = useRef();
const [image, setImage] = useState(null);
const changeBackground = () => {
setNavbar(window.scrollY > 0);
};
useEffect(() => {
window.addEventListener("scroll", changeBackground);
}, []);
function handleStepIndicator() {
if (step === 1) {
return "Step 1. Create your keychains";
} else if (step === 2) {
return "Step 2. Delivery Informations";
} else if (step === 3) {
return "Step 3. Payment Method";
}
}
const [hasOrdered, setHasOrdered] = useState(false);
return (
<>
{hasOrdered && (
<>
<div className="overlay" onClick={() => setHasOrdered(false)} />
<div className="purchaseModal">
<img src={thanks} alt="thanks" className="thanksImage"></img>
<h2>Thank you for your purchase</h2>
<p className="purchaseInfo">
We will inform you about the package via phone number that you
gave us
</p>
</div>
</>
)}
<div className="top" ref={topRef} style={{ marginTop: "-2rem" }} />
<section className="hero">
<div
className={`hero__navbar ${navbar && "active"}`}
onClick={() => {
topRef.current?.scrollIntoView({ behavior: "smooth" });
}}
>
<h2
className="hero__nav"
onClick={() => {
topRef.current?.scrollIntoView({ behavior: "smooth" });
}}
>
KEYCH
</h2>
</div>
<div className="hero__about">
<h1 className="hero__headline">BRING YOUR KEYCHAIN IDEAS TO LIFE</h1>
<p className="hero__support">
We make handmade and customized keychains using images that you like
</p>
</div>
<button
className="hero__cta"
onClick={() => {
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
}}
>
<h3>Create Now</h3>
</button>
</section>
<section className="creation">
<h1 className="creation__stepIndicator">{handleStepIndicator()}</h1>
{step === 1 && (
<Step1
image={image}
setImage={setImage}
orders={orders}
setOrders={setOrders}
setStep={setStep}
/>
)}
{step === 2 && (
<Step2
customerName={customerName}
setCustomerName={setCustomerName}
customerNumber={customerNumber}
setCustomerNumber={setCustomerNumber}
customerAddress={customerAddress}
setCustomerAddress={setCustomerAddress}
setStep={setStep}
/>
)}
{step === 3 && (
<Step3
orders={orders}
setOrders={setOrders}
customerName={customerName}
customerAddress={customerAddress}
customerNumber={customerNumber}
setCustomerName={setCustomerName}
setCustomerAddress={setCustomerAddress}
setCustomerNumber={setCustomerNumber}
setHasOrdered={setHasOrdered}
setStep={setStep}
/>
)}
</section>
<div className="bottom" ref={bottomRef} />
</>
);
}
function OrderInfo(props) {
return (
<div className="orderInfo">
<div className="info__segment" style={{ marginBottom: "3rem" }}>
<h1>{props.id}</h1>
<h5>Order ID</h5>
</div>
{props.orders.map((o, i) => (
<div className="keychainInfo">
<h1>Keychain No. {i + 1}</h1>
<div className="info__segment">
<img
className="keychainImage"
src={o.keychainImage}
alt="keychainImage"
/>
<h5>Keychain Image</h5>
</div>
{o.keychainMessage && (
<div className="info__segment">
<h3 className="keychainMessage">{o.keychainMessage}</h3>
<h5>Keychain Message</h5>
</div>
)}
</div>
))}
<div className="customerInfo">
<div className="info__segment">
<h3 className="customerName">{props.customerName}</h3>
<h5>Customer Name</h5>
</div>
<div className="info__segment">
<h3 className="customerNumber">{props.customerNumber}</h3>
<h5>Customer Number</h5>
</div>
<div className="info__segment">
<h3 className="customerAddress">{props.customerAddress}</h3>
<h5>Customer Address</h5>
</div>
<div className="info__segment">
<h3 className="customerAddress">{props.paymentMethod}</h3>
<h5>Payment Method</h5>
</div>
<div className="info__segment">
<h3 className="totalPrice">₱ {props.price}</h3>
<h5>Total Price</h5>
</div>
</div>
</div>
);
}
function OrderManagement() {
const [orders, setOrders] = useState([]);
useEffect(
() =>
onSnapshot(
query(collection(db, "orders"), orderBy("timestamp", "desc")),
(snapshot) => {
setOrders(snapshot.docs);
}
),
[]
);
return (
<section className="orders">
<section className="toApprove orders__section">
<h1 className="segmentTitle">To Approve</h1>
{orders
.filter((o) => o.data().status === "toApprove")
.map((o) => (
<div className="toApproveOrder Order">
<OrderInfo
key={o.id}
orders={o.data().orders}
customerName={o.data().customerName}
customerAddress={o.data().customerAddress}
customerNumber={o.data().customerNumber}
price={o.data().price}
id={o.id}
paymentMethod={o.data().paymentMethod}
/>
<div className="toApproveControls controls">
<button
className="declineButton controlButton decline"
onClick={() => {
deleteDoc(doc(db, "orders", o.id));
}}
>
Decline
</button>
<button
className="approveButton controlButton"
onClick={() => {
updateDoc(doc(db, "orders", o.id), {
status: "toCreate",
});
}}
>
Approve
</button>
</div>
</div>
))}
</section>
<section className="toCreate orders__section">
<h1 className="segmentTitle">To Create</h1>
{orders
.filter((o) => o.data().status === "toCreate")
.map((o) => (
<div className="Order">
<OrderInfo
key={o.id}
orders={o.data().orders}
customerName={o.data().customerName}
customerAddress={o.data().customerAddress}
customerNumber={o.data().customerNumber}
price={o.data().price}
id={o.id}
paymentMethod={o.data().paymentMethod}
/>
<div className="controls">
<button
className="controlButton"
onClick={() => {
updateDoc(doc(db, "orders", o.id), {
status: "toShip",
});
}}
>
Ship Order
</button>
</div>
</div>
))}
</section>
<section className="toShip orders__section">
<h1 className="segmentTitle">To Ship</h1>
{orders
.filter((o) => o.data().status === "toShip")
.map((o) => (
<div className="Order">
<OrderInfo
key={o.id}
orders={o.data().orders}
customerName={o.data().customerName}
customerAddress={o.data().customerAddress}
customerNumber={o.data().customerNumber}
price={o.data().price}
id={o.id}
paymentMethod={o.data().paymentMethod}
/>
<div className="controls">
<button
className="controlButton"
onClick={() => {
deleteDoc(doc(db, "orders", o.id));
}}
>
Complete Order
</button>
</div>
</div>
))}
</section>
</section>
);
}
function Admin() {
const securityPassword = "Pogi Ni Vlad";
const [password, setPassword] = useState("");
return password === securityPassword ? (
<OrderManagement />
) : (
<section className="login">
<h1 className="title">Keych Admin Login</h1>
<div className="login__form">
<input
type="text"
className="form__pasword"
placeholder="Input password to enter: "
value={password}
onChange={(e) => setPassword(e.target.value)}
></input>
</div>
</section>
);
}
function App() {
return (
<PayPalScriptProvider
options={{
"client-id": process.env.REACT_APP_PAYPAL_CLIENT_ID,
currency: "PHP",
}}
>
<Router>
<div className="app">
<Routes>
<Route path="/" element={<LandingPage />}></Route>
<Route path="/admin" element={<Admin />}></Route>
</Routes>
</div>
</Router>
</PayPalScriptProvider>
);
}
export default App;
Where is the PayPalButtons component in the first code sample?
Consider using the full sample the package provides as a base. There's a currency variable set in two locations (line 10 and later within the PayPalScriptProvider) for whatever reason.

How can i setState for color change

I already have the condition, but i need to set the state, if i setColor on the if method, give me error- Too many re-renders. React limits the number of renders to prevent an infinite loop.
State:
const [color, setColor] = useState();
Map:
{data.map((doc) => {
let verificacao = "";
if (doc.status === "Não Necessário") {
verificacao = "Proxima Verificação:";
setColor(true)
} else if (doc.status === "Verificado e Conforme") {
verificacao = "Data:";
setColor(false)
} else {
console.log("ERRO");
}
return (
The span i want to change the color:
<div className="row">
<div className="pontos">
<span className={color ? "red" : "green"}>
{doc.status}
</span>
<span className="data-status">{verificacao}</span>
{JSON.stringify(
doc.dateVerificado
.toDate()
.toISOString()
.replace(/T.*/, "")
.split("-")
.reverse()
.join("-")
)}
</div>
</div>
Full Code:
import React, { useEffect, useState } from "react";
import { Button } from "react-bootstrap";
import ManutencaoDataService from
"../../Services/ManutecaoDataService";
import "./ManutencaoInfo.css";
const ManutencaoInfo = ({ getDataId }) => {
const [data, setData] = useState([]);
const [color, setColor] = useState();
useEffect(() => {
getData();
return () => {
setData([]);
};
}, []);
const getData = async () => {
const data = await ManutencaoDataService.getAllData();
console.log(data.docs);
setData(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
};
const deleteHandler = async (id) => {
await ManutencaoDataService.deleteData(id);
getData();
};
return (
<>
<div className=" container mb-2">
<Button variant="dark edit" onClick={getData}>
Atualizar Lista
</Button>
</div>
{/* <pre>{JSON.stringify(books, undefined, 2)}</pre>} */}
{data.map((doc) => {
let verificacao = "";
if (doc.status === "Não Necessário") {
verificacao = "Proxima Verificação:";
setColor(true)
} else if (doc.status === "Verificado e Conforme") {
verificacao = "Data:";
setColor(false)
} else {
console.log("ERRO");
}
return (
<div key={doc.id} className="container-principal">
<div className="container">
<div className="row relatorio">
<div className="col">
<div className="departamento">
<h3>{doc.departamentos}</h3>
</div>
</div>
</div>
<div className="row detalhes">
<div className="col">
<div className="row">
<div className="pontos">
<span className="identificacao">Equipamento:
</span>
{doc.equipamentos}
</div>
</div>
<div className="row">
<div className="pontos">
<span className="identificacao">Responsável:
</span>
{doc.responsaveis}
</div>
</div>
<div className="row">
<div className="pontos">
<span className="codigo">{doc.codigos.codigo}
</span>
<span className="tipo">{doc.tipo}</span>
</div>
</div>
</div>
<div className="col ">
<div className="row">
<div className="pontos">
<span className="identificacao">Data Manutenção:
</span>
{JSON.stringify(
doc.dateManutencao
.toDate()
.toISOString()
.replace(/T.*/, "")
.split("-")
.reverse()
.join("-")
)}
</div>
</div>
<div className="row">
<div className="pontos">
<span className={color ? "red" : "green"}>
{doc.status}
</span>
<span className="data-status">{verificacao}</span>
{JSON.stringify(
doc.dateVerificado
.toDate()
.toISOString()
.replace(/T.*/, "")
.split("-")
.reverse()
.join("-")
)}
</div>
</div>
<div className="row">
<div className="pontos">{doc.codigos.observacoes}
</div>
</div>
</div>
</div>
<div className="row botoes">
<div className="col">
<span className="botao-editar">
<Button
variant="secondary"
className="edit"
onClick={(e) => getDataId(doc.id)}
>
Editar
</Button>
</span>
<span className="botao-apagar">
<Button
variant="danger"
className="delete"
onClick={(e) => deleteHandler(doc.id)}
>
Apagar
</Button>
</span>
</div>
</div>
</div>
</div>
);
})}
</>
);
};
export default ManutencaoInfo;
Instead of using state, I would recommend using doc's status property for using the correct CSS class like this:
<span className={doc.status === "Não Necessário" ? "red" : "green"}>
{doc.status}
</span>
import React, { useEffect, useState } from "react";
import { Button } from "react-bootstrap";
import ManutencaoDataService from
"../../Services/ManutecaoDataService";
import "./ManutencaoInfo.css";
import classNames from 'classnames';
const ManutencaoInfo = ({ getDataId }) => {
const [data, setData] = useState([]);
useEffect(() => {
getData();
}, []);
const getData = async () => {
const data = await ManutencaoDataService.getAllData();
console.log(data.docs);
setData(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
}
return (
<>
...
{data.map((doc) => {
return (
<div key={doc.id} className="container-principal">
<div className="container">
...
<div className="row detalhes">
...
<div className="col ">
...
<div className="row">
<div className="pontos">
<span className={classNames({red: doc.status === "Não Necessário", green:doc.status === "Verificado e Conforme" })}>
{doc.status}
</span>
<span className="data-status">{
doc.status === "Não Necessário" ? "Proxima Verificação:" : doc.status === "Verificado e Conforme" ? "Data:" :""
}</span>
....
</div>
</div>
....
</div>
</div>
...
</div>
</div>
);
})}
</>
);
};
export default ManutencaoInfo;
create a new component which renders inside the map function, it will be better to maintain
I think you are overcomplicating it with introducing state variable.
You can just use local variable in your function like this:
// Remove this state
// const [color, setColor] = useState();
{data.map((doc) => {
let verificacao = "";
let color; // add this var
if (doc.status === "Não Necessário") {
verificacao = "Proxima Verificação:";
color = 'red' // changed
} else if (doc.status === "Verificado e Conforme") {
verificacao = "Data:";
color = 'green' // changed
} else {
console.log("ERRO");
}
return (
// ...
<span className={color}> {/* changed */}
{doc.status}
</span>
// ...
)

Cannot read property 'map' of undefined in react -js

this is the hole component
import React ,{useState} from 'react';
import useSWR from 'swr'
import Axios from "axios"
import Nav from '../home/nav';
import './mission.css';
import '../home/Cards.css';
import CardItem from '../home/CardItem';
import SweetAlert from 'sweetalert2-react';
const PostuleMission=(props)=>{
const [show,setShow]=useState(false);
const [donnee,setDonnee]=useState({ missions: [] });
const [acceper,setEstaccepe]=useState(0);
const handelAccept =(mission)=>{
//alert("http://localhost:8080/BricoAccept/"+props.user.id+"/"+mission+"/1")
Axios.put("http://localhost:8080/BricoAccept/"+props.user.id+"/"+mission+"/1")
.then(res=>{
setShow(true)
})
.catch(err =>{
alert(err)
})
}
const fetcher = (url) => fetch(url).then(res =>{return res.json()} )
const { data, error } = useSWR('http://localhost:8080/bricoleurs/'+props.user.id, fetcher)
if (error) return (
<div className="d-flex flex-column">
<img alt="..." src="/assets/logo.png" style={{height:"100px",width:"100px"}} className="logo" />
<p className="text-danger">failed to load</p>
</div>);
if (!data) {return (
<div>
<img alt="..." src="/assets/logo.png" className="logo" />
<div className="d-flex flex-row" style={{position:"absolute",left:"50%",right:"50%",top:"45%" }}>
<div className="spinner-grow text-primary" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-secondary" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-success" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-danger" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-warning" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-info" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-light" role="status">
<span className="visually-hidden">Loading...</span>
</div>
<div className="spinner-grow text-dark" role="status">
<span className="visually-hidden">Loading...</span>
</div>
</div>
</div>);}
//les cartes
setDonnee(data.missions)
//const Missionss = (data.missions)?((data.missions[0].accepterBrico)?data.missions: []):[];
const Missions= data.missions.map((item)=>{
console.log("hello"+ item.id);
// setEstaccepe(0)
/* Axios.get("http://localhost:8080/accepterbrico/"+props.user.id+"/"+item.id)
.then(res=>{
*/
// alert(item.accepterBrico[0].bricoId)
/*
if(item.accepterBrico) {
for( let i=0;i < item.accepterBrico.length;i++){
if(item.accepterBrico[i].bricoId==props.user.id && item.accepterBrico[i].missionId ==item.id){
if(item.accepterBrico[i].clientAccept==1 && item.accepterBrico[i].bricoAccept==1 ){
setEstaccepe(1) ;
}
else if( item.accepterBrico[i].clientAccept==1 && item.accepterBrico[i].bricoAccept==0 ){
setEstaccepe(2) ;
}
else{
setEstaccepe(0) ;
}
}
}}
*/
const id=item.id;
return(
<div className='cards'>
<div className='cards__container'>
<CardItem
key={item.id}
src={item.images}
text={item.mission_description}
label={item.titre_mission}
path='/comment'
/>
{(acceper==2)? <div className="d-flex flex-row align-items-around p-3">
<button onClick={()=>handelAccept(item.id)} className="btn btn-outline-success">Accepter</button>
<button className="btn btn-outline-danger">Refuser</button>
</div>:((acceper==1)?<div style={{color:"green",fontSize:"2em"}} ><p>Vous l'avais accepté</p></div>:<div style={{color:"red",fontSize:"2em"}} >Pas de réponse</div>)}
</div>
</div>
)
/* })
.catch(err =>{
alert(" inside "+err)
})*/
}
);
return(
<div >
<div id="postulemission"></div>
<Nav data={props.user} />
<div id="postulebox">
<h1>MinuteBlog</h1>
<SweetAlert
show={show}
title="Success"
icon='warning'
text="Congratulations vous avez bien obtenu la mission"
onConfirm={() => {
setShow(false)
}}
/>
{Missions}
</div>
</div>
);
}
export default PostuleMission;
i have a problem in my react code
when i use a loop function( so i can get the data from a list of object that i gave to the map) the map method doesn't read the data that i send to it anymore
this's the map :
enter code
const Missions = data.missions.map((item) => {
if (item.accepterBrico.length > 0) {
for (let i=0; i < item.accepterBrico.length; i++) {
if (item.accepterBrico[i].bricoId == props.user.id && item.accepterBrico[i].missionId == item.id) {
if (item.accepterBrico[i].clientAccept == 1 && item.accepterBrico[i].bricoAccept == 1) {
dosomething;
}
}
}
}
return (<div>..... </div>)
});
here is what the data sent to the map :
{
"id": 591,
"descriptionProfil": null,
"adresse": "harchi",
"phone": "",
"missions": [
{
"id": 586,
"titre_mission": "client#gmail.com",
"state": "Urgent",
"
"bricoleur_choisi": 0,
"idmission": 0,
"accepterBrico": [{
"id": 603,
"bricoId": 591,
"missionId": 597,
"clientAccept": 0,
"bricoAccept": 0
}]
},
details detailsdetailsdetailsdetailsdetailsdetailsdetailsdetails
Issue
All the error is saying is that on at least one of your component renders is that data.missions is not defined. I suspect it is on the initial render because you've not defined accurate enough initial state.
Solution(s)
You can define better initial state that matches what you are attempting to render on the initial render cycle. { missions: [] } as initial data state value would be sufficient in ensuring data.missions is defined and mappable on the initial render cycle.
const [data, setData] = useState({ missions: [] });
You can use a guard clause or Optional Chaining (otherwise known as null-checks) to guard against accessing into potentially null or undefined objects.
const Missions = data.missions && data.missions.map((item) => { .... });
or
const Missions = data.missions?.map((item) => { .... });
or provide a fallback value
const Missions = (data.missions || []).map((item) => { .... });

How can I pass a data to another component from a list with React?

I got stuck in a part of my code. Basically I have a list and I would like to show more info when I click on item, I have a modal and I would like to show this details on a modal. I managed to pass some information, however, when I pass the array it displays only the last item in the list and I would like to display exactly the one I clicked.
**MODAL COMPONENT**
const Modal = ({ object, modal, setModal }) => {
if (modal)
return (
<div className="modal">
<div className="modal-body">
<div className="modal-header">
<span className="modal-title">{object.title}</span>
<span className="modal-date">xxxxx</span>
</div>
<div className="modal-content">
<div>
<span className="sinopse-style">Overview</span>
<hr></hr>
<p className="modal-description">xxx</p>
</div>
</div>
<div className="modal-footer">
<div className="tags">
<p className="tag-style">Ação</p>
<p className="tag-style">Aventura</p>
<p className="tag-style">Fantasia</p>
</div>
<div className="match-background">
<span className="match-title">75%</span>
</div>
</div>
<h1 onClick={() => setModal(false)}>Close Modal</h1>
</div>
</div>
);
return null;
};
export default Modal;
**RESULTS COMPONENT**
const Movies = (props) => {
const [data, setData] = React.useState("");
const [modal, setModal] = React.useState(false);
const [currentPage, setCurrentPage] = React.useState(1);
const [dataPerPage, setDataPerPage] = React.useState(5);
React.useEffect(() => {
const fetchData = async () => {
await fetch(API).then((response) =>
response
.json()
.then((json) => setData(json))
.catch((error) => console.log(error))
);
};
fetchData();
}, []);
function openModal() {
!modal ? setModal(true) : setModal(false);
}
// Get data per page
const indexLastData = currentPage * dataPerPage;
const indexFirstData = indexLastData - dataPerPage;
const currentData = data && data.results.slice(indexFirstData, indexLastData);
// console.log("current: " + data && currentData);
const paginate = (pageNumber) => setCurrentPage(pageNumber);
return (
<>
{data &&
currentData.map((object) => (
<div className="movies-container" key={object.id} onClick={openModal}>
<div>
<img
className="movie-billboard"
src={`https://image.tmdb.org/t/p/w185${object.poster_path}`}
/>
</div>
<div className="rightSideMovie">
<div className="header-movie-title">
<span className="movie-title">{object.title}</span>
</div>
<div className="match">
<span className="match-percentual">
{object.vote_average * 10}%
</span>
</div>
<span className="release-date">{object.release_date}</span>
<div className="movie-description">
<span>{object.overview}</span>
</div>
</div>
<Modal modal={modal} object={object} setModal={setModal} />
</div>
))}
<Pagination
dataPerPage={dataPerPage}
totalData={data && data.results.length}
paginate={paginate}
/>
</>
);
};
You could tweak your code a bit to select the movie from the list and only have 1 modal. Right now just the last modal will be there since you are using state outside the map.
**MODAL COMPONENT**
// No need to pass in modal -- just pass in the selectedMovie here because that is what you care about
const Modal = ({ selectedMovie, hideModal }) => {
if (selectedMovie)
return (
<div className="modal">
<div className="modal-body">
<div className="modal-header">
<span className="modal-title">{selectedMovie.title}</span>
<span className="modal-date">xxxxx</span>
</div>
<div className="modal-content">
<div>
<span className="sinopse-style">Overview</span>
<hr></hr>
<p className="modal-description">xxx</p>
</div>
</div>
<div className="modal-footer">
<div className="tags">
<p className="tag-style">Ação</p>
<p className="tag-style">Aventura</p>
<p className="tag-style">Fantasia</p>
</div>
<div className="match-background">
<span className="match-title">75%</span>
</div>
</div>
<h1 onClick={hideModal}>Close Modal</h1>
</div>
</div>
);
return null;
};
export default Modal;
**RESULTS COMPONENT**
const Movies = (props) => {
const [data, setData] = React.useState("");
// Just store the selected movie here
const [selectedMovie, setSelectedMovie] = useState(null);
const [currentPage, setCurrentPage] = React.useState(1);
const [dataPerPage, setDataPerPage] = React.useState(5);
React.useEffect(() => {
const fetchData = async () => {
await fetch(API).then((response) =>
response
.json()
.then((json) => setData(json))
.catch((error) => console.log(error))
);
};
fetchData();
}, []);
// Get data per page
const indexLastData = currentPage * dataPerPage;
const indexFirstData = indexLastData - dataPerPage;
const currentData = data && data.results.slice(indexFirstData, indexLastData);
// console.log("current: " + data && currentData);
const paginate = (pageNumber) => setCurrentPage(pageNumber);
return (
<>
{data &&
currentData.map((object) => (
<div className="movies-container" key={object.id} onClick={() => setSelectedMovie(object)}>
<div>
<img
className="movie-billboard"
src={`https://image.tmdb.org/t/p/w185${object.poster_path}`}
/>
</div>
<div className="rightSideMovie">
<div className="header-movie-title">
<span className="movie-title">{object.title}</span>
</div>
<div className="match">
<span className="match-percentual">
{object.vote_average * 10}%
</span>
</div>
<span className="release-date">{object.release_date}</span>
<div className="movie-description">
<span>{object.overview}</span>
</div>
</div>
</div>
))}
// Hiding the modal is just simply setting the selectedMovie to null
<Modal selectedMovie={selectedMovie} hideModal={() => setSelectedMovie(null)} />
<Pagination
dataPerPage={dataPerPage}
totalData={data && data.results.length}
paginate={paginate}
/>
</>
);
};

React trigger only one element in array

I am in the process of making a comment system like the one on youtube. In my implementation, when I click on modify, all comments are now inputs but only the value of the selected input will be modified. how to trigger only the element i clicked.
as you can see it triggers all the array elements
function App() {
const [open, setOpen] = useState(false);
return (
<div className="container mt-5">
<MDBRow>
{data &&
data.map((item) => (
<MDBCol md="7" lg="7" key={item.id} className="mb-4">
{!open && (
<>
<div className="font-weight-bolder float-left pr-2">
{item.name}
</div>
<div className="float-right pr-2">
<button
onClick={() => {
setOpen(true);
}}
>
Modifier
</button>
</div>
</>
)}
{open && (
<UpdateData
id={item.id}
name={item.name}
onAbort={() => setOpen(false)}
submit={() => setOpen(false)}
/>
)}
</MDBCol>
))}
</MDBRow>
</div>
);
}
export const UpdateData = ({ name, id, onAbort, submit }) => {
const formik = useFormik({
initialValues: {
id: id,
name: name,
},
onSubmit: async (values) => {
console.log(values);
submit();
},
});
return (
<form onSubmit={formik.handleSubmit}>
<MDBInput
value={formik.values.name}
name="name"
onChange={formik.handleChange}
/>
<div className="float-right">
<span onClick={onAbort} className="text-capitalize grey-text">
Cancel
</span>
<button type="submit">confirm</button>
</div>
</form>
);
};
And this is the sandbox
that i have created
To trigger only one element to be clicked you have to pass the index
function App() {
const [open, setOpen] = useState(false);
const [selectedRow, setSelectedRow] = useState(undefined);
const onSelectedRow = (index) => {
setSelectedRow(index);
setOpen(true);
}
return (
<div className="container mt-5">
<MDBRow>
{data &&
// here you will get the index
data.map((item,index) => (
<MDBCol md="7" lg="7" key={item.id} className="mb-4">
{!open && (
<>
<div className="font-weight-bolder float-left pr-2">
{item.name}
</div>
<div className="float-right pr-2">
// Now onClick pass the index of selected row to onSelectedRow
<button
onClick={() =>onSelectedRow(index)}
>
Modifier
</button>
</div>
</>
)}
// here add condition to open selected row
{ (open === true && selectedRow === index) ? (
<UpdateData
id={item.id}
name={item.name}
onAbort={() => setOpen(false)}
submit={() => setOpen(false)}
/>
) : null
}
</MDBCol>
))}
</MDBRow>
</div>
);
}
Sandbox code https://codesandbox.io/s/youthful-wave-k4eih?file=/src/App.js
If you have any queries comment below!
instead of having a false default value in your hook you should have a unique key for each element. By default, it applies to all elements.

Categories

Resources