我的应用是配方搜索。我从API获得了一个搜索表单和一个提交按钮,以及配方结果。 我有查询状态变量(用useState()声明),我尝试使用搜索表单上的onSubmit函数对其进行更新。因此,我的想法是:有人在搜索栏中键入内容,然后提交查询。 MY onSubmit使用当前值并尝试设置查询。 问题是,我的查询总是延迟1个渲染。默认查询为“鸡肉”,因此,如果我输入“ cocoa”并单击“提交”,则API将为我提供鸡肉的结果,如果我在战后输入“ carrot”,则现在将获得“ cocoa”的结果。显然我错过了一些东西,因为我的状态跟不上变化。
还有一个额外的问题,如果发生这种情况是因为我没有在useEffect中调用getRecipes函数(相反,我只是提到了它)。如果我打电话给我,我会得到一个错误:
未捕获的TypeError:destroy不是函数 和 index.js:1375警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。
我的代码:
import React, { useEffect, useState, useRef } from "react";
import logo from "./logo.svg";
import Recipe from "./Recipe";
import "./App.css";
const App = () => {
const APP_ID = "c49a2xxx";
const APP_KEY = "0fbf56f642af60a29a73841f1fbdcxxx";
const [recipes, setRecipes] = useState([]);
//const [search, setSearch] = useState("");
const [query, setQuery] = useState("chicken");
const search = useRef();
const exampleRequest = `https://api.edamam.com/search?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`;
useEffect(() => getRecipes, []);
useEffect(() => getRecipes, [query]);
const getRecipes = async () => {
const response = await fetch(exampleRequest);
const data = await response.json();
setRecipes(data.hits);
};
const submitSearch = (e) => {
e.preventDefault();
setQuery(search.current.value);
};
return (
<div className="App">
<form onSubmit={submitSearch}>
<input type="text" ref={search} />
<button type="submit">Search</button>
</form>{" "}
{recipes.map((recipe, key) => (
<Recipe
key={key}
title={recipe.recipe.label}
calories={recipe.recipe.calories}
img={recipe.recipe.image}
/>
))}
</div>
);
};
export default App;
答案 0 :(得分:1)
我认为内存泄漏错误可能是由这两种影响引起的。
// Declared outside the component since it'll never change
const APP_ID = 'c49a2xxx';
const APP_KEY = '0fbf56f642af60a29a73841f1fbdcxxx';
const App = () => {
const [recipes, setRecipes] = useState([]);
const [query, setQuery] = useState('chicken');
const search = useRef();
// useEffect(() => getRecipes, []); You don't need two effects that does the same task
useEffect(() => {
const getRecipes = async () => {
// request url with params declared inside the function
// to make sure you're using the updated state variable
const exampleRequest = `https://api.edamam.com/search?q=${query}&app_id=${APP_ID}&app_key=${APP_KEY}`;
const response = await fetch(exampleRequest);
const data = await response.json();
setRecipes(data.hits);
};
getRecipes();
}, [query, APP_ID, APP_KEY]);
const submitSearch = e => {
e.preventDefault();
setQuery(search.current.value);
};
return (
<div className="App">
<form onSubmit={submitSearch}>
<input type="text" ref={search} />
<button type="submit">Search</button>
</form>
{recipes.map((recipe, key) => (
<Recipe
key={key}
title={recipe.recipe.label}
calories={recipe.recipe.calories}
img={recipe.recipe.image}
/>
))}
</div>
);
};
如果您想了解有关中止中断获取的更多信息,这是我发现有用的文章。
https://itnext.io/how-you-can-abort-fetch-request-on-a-flight-830a639b9b92