У меня есть асинхронная функция внутри useEffect для извлечения данных на основе заданного ввода из базы данных (mongodb) с использованием Express.js. При отправке формы она должна передать состояние (введенные данные) на сервер и найти данные, а затем вернуть результат обратно в интерфейс. Но при отправке отправить пустое состояние и вернуть пустой массив.
Компонент реакции: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 handleChangeEvent(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 = {handleChangeEvent}
value = {compare.proId1}
/>
<input
type = "text"
className = "proId2"
placeholder = "proId2"
name = "proId2"
onChange = {handleChangeEvent}
value = {compare.proId2}
/>
<button
className = "submit"
onClick = {
React.useEffect(() => {
fetchData()
},[fetchData])
}
>
SUBMIT
</button>
</form>
</div>
<Result />
</>
);
}
` сервер:
`
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" });
}
});
` ожидаемый запрос:
`
{
"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
}
]
`
да, я устанавливаю состояние «сравнить» всякий раз, когда значение в поле ввода изменяется.
Итак, если вы console.info(compare.proId1, compare.proId2)
внутри useCallback
перед const response
, он показывает правильные значения?
НЕТ, он также пуст. Почему не устанавливается «сравнить»?
Чувак, быстрое исправление => onClick = { fetchData }, массив зависимостей useCallback [compare.proId1, compare.proId2], проверьте новые документы React beta.reactjs.org/learn/synchronizing-with-effects, в целом поможет , ваше здоровье
Ты неправильно используешь хуки.
Рекомендую внимательно прочитать эту статью и обратить внимание на useCallback и useEffect.
onClick = {
React.useEffect(() => {
fetchData()
},[fetchData])
}
это не способ использования useEffect.
onClick вы хотите загрузить свои данные, так что сделайте
onClick = {fetchData}
Кроме того, useCallback без зависимостей также является бесшовным, это хук для запоминания, который содержит значения дохода, чтобы избежать подпрыгивания. Таким образом, вы можете поместить свое состояние в его зависимость, но мне это кажется немного чрезмерным, и вы можете использовать его без обёртки useCallback.
внутри вашего обработчика fetchData вы хотите поместить результат в состояние, чтобы отобразить его позже, поэтому определите состояние для результата и установите его внутри обработчика.
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]);
и поместите куда-нибудь в свой возврат рендеринга
apiResponse.map(({ id, name }) => (<div key = {id}>{name}</div>))
я исправил это с помощью приведенного выше кода, но когда я нажимаю кнопку отправки, он просто консоль на секунду, а затем немедленно исчезает ... на вкладке «Сеть» не отображается никакого статуса.
Но вы отображали это где-то в коде? Состояние не будет отображаться на экране, если вы не поместите его где-нибудь в свой код. где ты хочешь это показать?
я хочу отобразить «apiResponse» в дочернем компоненте. Я попытался передать «apiResponse» в качестве опоры в дочерний элемент и консоль оттуда, но он показывает (на консоли) пустой массив
Спасибо, братан... я понял. Передача "события" в асинхронную функцию, а затем использование event.preventDefault() исправит проблему с исчезновением консоли... большое спасибо за вашу помощь, так как я новичок в кодирование и реакция
Вы проверили, что состояние установлено правильно, перед запуском запроса?