I have an async function inside useEffect to fetch data based on given input from database(mongodb)using Express.js. On submitting the form it should pass the state(inputs given) into server and find data then return the result back to front end. But while submitting it send empty state and returning empty array.
React Component:Compare.js `
import React, { useState, useCallback } from "react";
import { useEffect } from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Result from "./Result";
export default function () {
const [compare, setCompare] = useState({
proId1: "",
proId2: "",
});
function handleChange(event) {
const { value, name } = event.target;
setCompare((prevData) => ({
...prevData,
[name]: value,
}));
}
const fetchData = useCallback(async () => {
const response = await fetch("http://localhost:3000/api/compare", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
proId1: compare.proId1,
proId2: compare.proId2,
}),
});
const data = await response.json();
return data
}, []);
return (
<>
<div>
<h1>ENTER IDS TO COMPARE</h1>
<form>
<input
type="text"
className="proId1"
placeholder="proId1"
name="proId1"
onChange={handleChange}
value={compare.proId1}
/>
<input
type="text"
className="proId2"
placeholder="proId2"
name="proId2"
onChange={handleChange}
value={compare.proId2}
/>
<button
className="submit"
onClick={
React.useEffect(() => {
fetchData()
},[fetchData])
}
>
SUBMIT
</button>
</form>
</div>
<Result />
</>
);
}
` server:
`
app.post("/api/compare", async (req, res) => {
try {
let id1 = await req.body.proId1;
let id2 = await req.body.proId2;
let result = await model.find({ id: { $in: [id1, id2] } })
res.send(result)
} catch (error) {
res.json({ status: "error", error: "error" });
}
});
` expected Request:
`
{
"proId1":"1",
"proId2":"3"
}
expected Response
[
{
"_id": "637c5dddb9b084433f13d3f7",
"id": "1",
"name": "dffdf",
"price": "100$",
"ratings": "2",
"__v": 0
},
{
"_id": "637c5df3b9b084433f13d3fb",
"id": "3",
"name": "dffdf",
"price": "25$",
"ratings": "5",
"__v": 0
}
]
`
CodePudding user response:
You are using your hooks incorrectly.
I recommend you read this article gently and pay attention on useCallback and useEffect.
onClick={
React.useEffect(() => {
fetchData()
},[fetchData])
}
this is not the way to use useEffect.
onClick you want to load your data so do
onClick={fetchData}
Also useCallback without dependencies is also seamless, it is memoization hook that holds income values to avoid bouncing. So you can put your state into its dependency, but it seems to me a bit excessive and you can use it without useCallback wrapper.
inside of your fetchData handler you want to put the result into the state to display it later, so define state for the result and set it inside the handler
const [apiResponse, setApiResponse] = useState();
const fetchData = useCallback(async () => {
const response = await fetch("http://localhost:3000/api/compare", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
proId1: compare.proId1,
proId2: compare.proId2,
}),
});
const data = await response.json();
setApiResponse(data)
}, [compare]);
and put somewhere in your render return
apiResponse.map(({ id, name }) => (<div key={id}>{name}</div>))