How to delete data from server and UI using React and Node? - node.js

I want to delete data from UI and Server, I write this code, but the problem is when I click the Delete button data was deleted from UI but still exists in the server. After reloading the page deleted data showed in the UI again. when I console.log(data) the result is { acknowledged: true, deletedCount: 0 }.
/* server side code */
app.delete('/data/:id', async (req, res) => {
const id = req.params.id
const query = { _id: ObjectId(id) }
const result = await dataCollection.deleteOne(query)
res.send(result)
})
/* client side code */
const [data, setData] = useData()
const deleteData = async (id) => {
const confirmation = window.confirm('Are you sure about delete the data ?')
if (confirmation) {
const { data } = await axios.delete(`http://localhost:5000/data/${id}`, product)
const exist = data.filter( x => x._id !== id);
setData(exist)
})
}
The result { acknowledged: true, deletedCount: 0 }
Expected result { acknowledged: true, deletedCount: 1 }

There is some problem with your other code, you have used a custom hook as useData . Your server response indicates that data is deleted from server, try to fetch data again from server and update the ui content with that new data. I am leaving a working version demo below:
function SingleProductMng({ item, products, setProducts }) { // here props are drilled in parent container
// here item is the single item to render
// products and setProducts is custom useState hook to render data from server
const { _id, name, supplier, price, quantity, category } = item;
const handleDelete = () => {
if (window.confirm('Are you sure you want to delete?')) {
console.log('deleted');
fetch(`your server url`, {
method: 'DELETE',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify(item),
});
const filteredItem = products.filter((product) => product._id !== _id);
setProducts(filteredItem);
} else {
console.log('cancel');
}
};
return (<>components</>)

Related

why I get an empty request body express

Router
router.patch("/fav/:id", getFav);
controller
const getFav = async (req, res) => {
const { favToadd } = req.body;
const { id } = req.params;
try {
const Users = await User.findById(id);
console.log("body : ", req.body); // body : {}
const fav = await User.findByIdAndUpdate(id, {
$set: { favorite: [...Users.favorite, favToadd] },
});
res.send(fav);
} catch (error) {
console.log("err ", error.message);
}
};
//Function to add favorites
const response = await fetch(
`http://localhost:4000/api/user/fav/${currentUser._id}`,
{
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ prd: product.props }),
}
);
};
the item gets saved to MongoDB as null and then I take look at the req body it's empty,
my goal is to add an object to the favorite properties in MongoDB document
but it gets saved as null
try different methods but nothing works I don't think I get a body from the patch request
don't know if the problem with it or in the communication between the front and the back end it's
my first app so hopefully, the problem is in this line of code not in another part,
when I send it from postman with raw JSON it Works and gets saved at MongoDB with the properties I set

Getting a 400 Error while trying to decrease counter on clicking a button and saving that Data on Database

My Objective is to managing stock of Products. I have placed a button on product details page. On clicking that button, the stock of the products will be decreased by one and the updated stock will be stored in the Database.
What I've done shows the decrement of the products on the console, but 400 error shows along with it and the data is not getting saved on the Database.
The code I've written on the client-side-
const newQty = parseInt(product.quantity) - 1;
const quantity = newQty;
console.log(quantity);
const url = `http://localhost:5000/product/${productId}`;
fetch(url, {
method: 'PUT',
headers: {
'content-Type': 'application/json'
},
body: JSON.stringify(quantity)
})
.then(response => response.json())
.then(data => {
console.log(data);
setProduct(data)
})
}
Code on the Server-Side-
const id = req.params.id;
const newQty = req.body;
console.log(newQty);
const filter = { _id: ObjectId(id) };
const options = { upsert: true };
const updatedQty = {
$set: {
quantity: newQty.quantity
}
};
const result = await inventoryCollection.updateOne(filter, updatedQty, options);
res.send(result);
})
The Error I am having- errorImage
any help on this matter will be highly appreciated.

How can I remove a product as a seller and not have it appear in cart

Right now we are able to remove a product. When we remove a product we want the CART to reflect the changes. Meaning that if a user adds an item to CART and then the seller deletes the product for sale, the user will no longer see the product in cart.
Our MongoDB database is set up in this way:
Here's our code so far:
//DELETE PRODUCT
async function deleteProductInDb(uri_, seller_info) {
try {
const client = await MongoClient.connect(uri_, {
useUnifiedTopology: true, serverApi: ServerApiVersion.v1
});
const db = client.db("boreal_db");
var products_tb = db.collection("products");
const response = await products_tb.deleteOne({"_id": new ObjectID(seller_info._id)},{
})
client.close();
return response;
} catch(error) {
client.close();
console.log(error);
}
}
//DELETE PRODUCT
app.delete('/deleteProduct', function(req, res) {
console.log(req.body);
res.set({
'Access-Control-Allow-Origin': '*'
})
deleteProductInDb(uri, req.body).then(response => {console.log(response); res.send(response)});
});
// Custom useContext for the Cart
import React, { useReducer, useContext, createContext } from "react";
const CartStateContext = createContext();
const CartDispatchContext = createContext();
/*
Manage the state cart (array).
ADD: Add items to cart array
REMOVE: Remove item from cart array using index
Throws an error if different case.
*/
const reducer = (state, action) => {
switch (action.type) {
case "ADD":
return [...state, action.item];
case "REMOVE":
const newArr = [...state];
newArr.splice(action.index, 1);
return newArr;
case "REMOVEALL":
return [];
default:
throw new Error(`unknown action ${action.type}`);
}
};
/* Context could be imported everywhere in the application
Implemented as an array (list), with each item assigned a key.
*/
export const CartProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, []);
return (
<CartDispatchContext.Provider value={dispatch}>
<CartStateContext.Provider value={state}>
{children}
</CartStateContext.Provider>
</CartDispatchContext.Provider>
);
};
export const useCart = () => useContext(CartStateContext);
export const useDispatchCart = () => useContext(CartDispatchContext);

how to create poll using API with react functional component

this is my react js code and I want to connect with my node js API but I don't understand how to that ...!
import React, { useState } from "react";
import Poll from "react-polls";
// import "./styles.css";
/**
* https://stackoverflow.com/questions/65896319/react-js-class-poll-convert-into-react-hooks-poll
*/
// Declaring poll question and answers
const pollQuestion = "Youtube is the best place to learn ?";
const answers = [
{ option: "Yes", votes: 7 },
{ option: "No", votes: 2 },
{ option: "don't know", votes: 1 },
];
const Fakepolls = () => {
// Setting answers to state to reload the component with each vote
const [pollAnswers, setPollAnswers] = useState([...answers]);
// Handling user vote
// Increments the votes count of answer when the user votes
const handleVote = (voteAnswer) => {
setPollAnswers((pollAnswers) =>
pollAnswers.map((answer) =>
answer.option === voteAnswer
? {
...answer,
votes: answer.votes + 1,
}
: answer
)
);
};
return (
<div>
<Poll
noStorage
question={pollQuestion}
answers={pollAnswers}
onVote={handleVote}
/>
</div>
);
};
export default function App() {
return (
<div className="App">
<Fakepolls />
</div>
);
}
It work's fine with
// Declaring poll question and answers
const pollQuestion = "Youtube is the best place to learn ?";
const answers = [
{ option: "Yes", votes: 7 },
{ option: "No", votes: 2 },
{ option: "don't know", votes: 1 },
];
but I want to connect this poll with my API instead of Declaring it ..! this is my api- to get data -> ( router.get("/poll/:pollId", getPoll); //)
exports.getPoll = async (req, res, next) => {
try {
const { pollId } = req.params;
const polls = await Poll.findById(pollId);
if (!polls) throw new Error("no polls found");
res.status(200).json(polls);
} catch (error) {
error.status = 400;
next(error);
}
};
This is a postman image -
and this API for POST data- and my node js code -
exports.votes = async (req, res, next) => {
try {
/**
* 1. get the poll from db
* 2. check if the user already exists in any option
* 3. if user has already selected any option do nothing
* 4. if user has selected any other option remove from that option
* 5. if user does not exist in any option, insert his user id to selected option
*/
const { pollId } = req.params;
let { userId, answer } = req.body;
// get selected poll from db
const poll = await Poll.findById(pollId);
if (answer && poll) {
answer = answer.toLowerCase();
///Finf the Poll
let existingVote = null;
Object.keys(poll.options).forEach((option) => {
// loop on all options, check if the user already exists in any option
if (poll.options[option].includes(userId)) {
existingVote = option;
}
});
if (existingVote == null) {
// if there is no existing vote save it to db
try {
const push = {};
push[`options.${answer}`] = userId;
const update = await Poll.findByIdAndUpdate(
pollId,
{ $push: push },
{ upsert: true }
);
res.status(201).json(update);
} catch (err) {
error.status = 400;
next(error);
}
} else if (existingVote && existingVote.length > 0) {
// check if answer is same as previous, if yes send not modified
if (existingVote.toLowerCase() === answer.toLowerCase()) {
res.status(304).send("Response already saved");
} else {
// delete the previous response and save it in new
if (
Array.isArray(poll.options[existingVote]) &&
poll.options[existingVote].length > 0
) {
// TODO: filtering this is not returning array but 1
poll.options[existingVote] = poll.options[existingVote].filter(
(vote) => vote != userId
);
poll.options[answer] = poll.options[answer].push(userId);
const update = await Poll.findByIdAndUpdate(pollId, {
$set: { options: poll.options },
});
res.status(201).json(update);
}
}
} else {
error = {
status: 500,
message: "Something went wrong",
};
next(error);
}
} else {
error = {
status: 404,
message: "Poll not found",
};
next(error);
}
} catch (error) {
error.status = 400;
next(error);
}
};
this is a POSTMAN image using POST to store data --- >
how can I connect API with react poll
What you'd do is make a fetch() to your /api/polls endpoint inside your Fakepolls component, the URL being exactly as you show in your Postman screenshot. More info on fetch here at the MDN docs.
With the response you get from the endpoint, populate the answers array you component uses. From what I see, it would require a bit of transformation as your answer object is not quite the same as what Poll needs.
Next, upon user action, as well as updating the votes in the UI, you need to make another fetch to your vote endpoint.
Here's your component again with these adjustments. Keep in mind it's untested and the URLs are obviously not real:
import React, { useState, useEffect } from "react";
import Poll from "react-polls";
// import "./styles.css";
/**
* https://stackoverflow.com/questions/65896319/react-js-class-poll-convert-into-react-hooks-poll
*/
const Fakepolls = () => {
// Setting answers to state to reload the component with each vote
const [pollQuestion, setPollQuestion] = useState('');
const [pollAnswers, setPollAnswers] = useState([]);
// Query the actual poll info from the server
useEffect(() => {
fetch('http://your-server/api/polls/you-poll-id')
.then((response) => response.json()) //parse response as json
.then((pollObject) => {
let answerCountDictionary = Object.keys(pollObject.options)
.map(oKey => {
return {
option: oKey,
anwers: pollObject.options[oKey].length
}
}); //iterate over the 'options' properties' keys to get the names and the current votes
setPollAnswers(answerCountDictionary);
setPollQuestion(pollObject.question)
})
.catch((error) => {
console.error('Error:', error);
});
},[]) //adding empty array of dependencies to prevent multiple calls on state change
// Handling user vote
// Increments the votes count of answer when the user votes
const handleVote = (voteAnswer) => {
setPollAnswers((pollAnswers) =>
pollAnswers.map((answer) =>
answer.option === voteAnswer
? {
...answer,
votes: answer.votes + 1,
}
: answer
)
);
//also submit the backend
fetch('http://your-server/api/vote/poll-id', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: {
"userId": "the-logged-in-user",
"answer": voteAnswer
},
})
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
};
return (
<div>
<Poll
noStorage
question={pollQuestion}
answers={pollAnswers}
onVote={handleVote}
/>
</div>
);
};
export default function App() {
return (
<div className="App">
<Fakepolls />
</div>
);
}

Why data is getting undefined on the server side coming from client side ? (reactjs to nodejs)

I am trying to send the data as parameters in GET route. But on server side when I am checking its undefined. What I am doing wrong?
Below is the React code:
P.S.: Here process.env.REACT_APP_API = localhost:5000/api
const App = () => {
const [state, setState] = useState({
page: 0,
search: "",
username: "Hey Baby!",
typingTimeout: 0,
load: true,
filter: ["search", "story", 0],
result: 0,
processTime: 0
});
const { page, search, username, typingTimeout, load, filter, result, processTime } = state;
const [posts, setPosts] = useState([]);
const fetchPosts = () => {
alert(filter); //Here I am getting the filter **array** values successfully
axios
.get(`${process.env.REACT_APP_API}/posts`,
{ page, search, username, typingTimeout, load, filter, result, processTime })
.then(response => {
console.log(response.data.datas);
setPosts(response.data.datas);
})
.catch(error => alert(error));
};
useEffect(() => {
fetchPosts();
}, []);
return (
----------html code------
)
}
Below is the Node Controller/Route code:
router.get('/posts', list); //route
exports.list = async(req, res) => { //controller
const { page, search, username, typingTimeout, load, filter, result, processTime } = req.body;
console.log("filter = " + filter);
console.log("page = " + page);
await Axios.get(
`http://hn.algolia.com/api/v1/${f1}?query=&tags=${f2}&page=${page}&numericFilters=created_at_i>0`
)
.then((r) => {
console.log(r.data.hits);
res.send({ datas: r.data.hits });
})
.catch((err) => {
console.log("err = "+ err);
});
};
This is what I am getting into the console in nodejs side:
[nodemon] restarting due to changes...
GET /api/posts - - ms - -
filter = undefined
page = undefined
Node Controller/Route f1 and f2 are not defined. Get API does not have req.body you should you req.query
const { page, search, username, typingTimeout, load, filter, result, processTime } = req.query;
You should pass as params, check npm package here
axios.get(`${process.env.REACT_APP_API}/posts`,
{
params: {
page,
search,
username,
typingTimeout,
load,
filter,
result,
processTime
}
}
)

Resources