Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 在React中与useState、useEffect和useRef混淆_Reactjs_React Hooks_React State - Fatal编程技术网

Reactjs 在React中与useState、useEffect和useRef混淆

Reactjs 在React中与useState、useEffect和useRef混淆,reactjs,react-hooks,react-state,Reactjs,React Hooks,React State,我的应用程序是配方搜索。一个搜索表单和一个提交按钮,以及我从API获得的配方结果。 我有一个查询状态变量(用useState()声明),我试图用搜索表单上的onSubmit函数更新它。所以,我的想法是:有人在搜索栏中键入一些内容,然后提交查询。MY onSubmit接受当前值并尝试设置查询。 问题是,我的查询总是延迟1次渲染。默认查询是“chicken”,所以如果我输入“cocoa”并点击submit,API将给出chicken的结果,如果我在战后输入“carrot”,现在我将得到“cocoa”

我的应用程序是配方搜索。一个搜索表单和一个提交按钮,以及我从API获得的配方结果。 我有一个查询状态变量(用useState()声明),我试图用搜索表单上的onSubmit函数更新它。所以,我的想法是:有人在搜索栏中键入一些内容,然后提交查询。MY onSubmit接受当前值并尝试设置查询。 问题是,我的查询总是延迟1次渲染。默认查询是“chicken”,所以如果我输入“cocoa”并点击submit,API将给出chicken的结果,如果我在战后输入“carrot”,现在我将得到“cocoa”的结果。很明显,我遗漏了一些东西,因为我的状态跟不上变化。

还有一个额外的问题,如果发生这种情况是因为我在useEffect中没有调用getRecipes函数(相反,我只是提到它)。如果我真的调用它,我会得到错误:

未捕获类型错误:销毁不是一个函数 js:1375警告:无法对未安装的组件执行React状态更新。这是一个no-op,但它表示应用程序中存在内存泄漏。要修复此问题,请取消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;
import React,{useffect,useState,useRef}来自“React”;
从“/logo.svg”导入徽标;
从“/Recipe”导入配方;
导入“/App.css”;
常量应用=()=>{
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,[]);
useffect(()=>getRecipes[query]);
const getRecipes=async()=>{
const response=等待获取(例如请求);
const data=wait response.json();
setRecipes(data.hits);
};
const submitSearch=(e)=>{
e、 预防默认值();
setQuery(search.current.value);
};
返回(
搜寻
{" "}
{recipes.map((recipe,key)=>(
))}
);
};
导出默认应用程序;

我认为内存泄漏错误可能是由这两种影响引起的

// 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>
  );
};

//在组件外部声明,因为它永远不会更改
const APP_ID='c49a2xxx';
const APP_KEY='0fbf56f642af60a29a73841f1fbdcxxx';
常量应用=()=>{
const[recipes,setRecipes]=useState([]);
const[query,setQuery]=useState('chicken');
const search=useRef();
//useEffect(()=>getRecipes,[]);您不需要两种效果来完成相同的任务
useffect(()=>{
const getRecipes=async()=>{
//在函数中声明参数的请求url
//确保您正在使用更新的状态变量
const exampleRequest=`https://api.edamam.com/search?q=${query}&app_id=${app_id}&app_key=${app_key}`;
const response=等待获取(例如请求);
const data=wait response.json();
setRecipes(data.hits);
};
getRecipes();
},[查询,应用程序ID,应用程序密钥];
const submitSearch=e=>{
e、 预防默认值();
setQuery(search.current.value);
};
返回(
搜寻
{recipes.map((recipe,key)=>(
))}
);
};
如果您想了解有关中止中断抓取的更多信息,我发现这篇文章很有用