React表单输入不更新API请求。

huangapple go评论65阅读模式
英文:

React form input for API Request is not updating

问题

I am trying to use the searchInput state as a variable for the api request. In the return statement, the button is not working as intended. The page refreshes and nothing is loaded. For some unknown reason, if React re-renders the page after being edited, it loads correctly.

import React, { useState, useEffect } from "react";
import "../../styles/components.css";
import './Recipes.css';

const key = 'API_KEY';

export default function Recipes() {

    const [posts, setPosts] = useState([]);
    const [searchInput, setSearchInput] = useState("");

    const recipesDisplay = posts?.map((response, i) => (
        <div key={response.id} className="list-group-item">
            <img src={response.image_url} />
            <h3 >{response.title}</h3>
            <p>By: {response.publisher}</p>
        </div>

    ));

    const handleChange = (e) => {
        e.preventDefault();
        setSearchInput(e.target.value);

    };

    const ShowPosts = () => {
        useEffect(() => {
            async function fetchData() {
                try {
                    const response = await fetch(`https://forkify-api.herokuapp.com/api/v2/recipes?search=${searchInput}&key=${key}`);
                    if (response.ok) {
                        const jsonResponse = await response.json();
                        console.log(searchInput);
                        await setPosts(jsonResponse.data.recipes);
                        await console.log(jsonResponse);
                    }
                } catch (err) {
                    console.log(err);
                }
            }
            fetchData();
        }, []);
    }

    return (
        <div className="main">
            <h1>Recipes</h1>
            <form>
                <input
                    type="search"
                    placeholder="Search here"
                    onChange={handleChange}
                    value={searchInput}
                />
                <button onClick={handleChange}>Submit</button>
            </form>

            {ShowPosts()}
            {recipesDisplay}

        </div>
    )
}

Note: I've removed the HTML entities and corrected the code formatting.

英文:

I am trying to use the searchInput state as a variable for the api request. In the return statement, the button is not working as intended. The page refreshes and nothing is loaded. For some unknown reason, if React re-renders the page after being edited, it loads correctly.

import React, {useState, useEffect} from &quot;react&quot;
import &quot;../../styles/components.css&quot;
import &#39;./Recipes.css&#39;
const key = &#39;API_KEY&#39;;
export default function Recipes() {
const [posts, setPosts] = useState([]);
const [searchInput, setSearchInput] = useState(&quot;&quot;);
const recipesDisplay = posts?.map((response, i) =&gt; (
&lt;div key={response.id} className=&quot;list-group-item&quot;&gt;
&lt;img src={response.image_url} /&gt;
&lt;h3 &gt;{response.title}&lt;/h3&gt;
&lt;p&gt;By: {response.publisher}&lt;/p&gt;
&lt;/div&gt;
));
const handleChange = (e) =&gt; {
e.preventDefault();
setSearchInput(e.target.value);
};
const ShowPosts = () =&gt; {
useEffect( () =&gt; { 
async function fetchData() {
try {
const response = await fetch(`https://forkify-api.herokuapp.com/api/v2/recipes?search=${searchInput}&amp;key=${key}`); 
if (response.ok) {
const jsonResponse = await response.json();
console.log(searchInput);
await setPosts(jsonResponse.data.recipes);
await console.log(jsonResponse);
}                    
} catch (err) {
console.log(err);
}
}
fetchData();
}, []);
}
return (
&lt;div className=&quot;main&quot;&gt;
&lt;h1&gt;Recipes&lt;/h1&gt;
&lt;form&gt;
&lt;input
type=&quot;search&quot;
placeholder=&quot;Search here&quot;
onChange={handleChange}
value={searchInput}
/&gt;
&lt;button onClick={handleChange}&gt;Submit&lt;/button&gt;
&lt;/form&gt;
{ShowPosts()}
{recipesDisplay}
&lt;/div&gt;
)
}

答案1

得分: 1

你不应该以这种方式将 useEffect 放在一个函数内部。你或许可以将你的函数包装在 useCallback 中,但是 useCallback 需要在函数外部。但你可能只需要在组件的初始渲染时根据其参数让 useEffect 完成其工作,而不必担心有一个名为 ShowPosts 的函数。

你内联的 recipesDisplay 变量将在每次渲染时返回一个新值,导致组件重新渲染的频率高于必要,可能会持续不断地重新渲染。这将导致 ShowPosts 不断运行。假设它能够在内部使用 useEffect 正常工作,这将不断地重置你的帖子/食谱,加剧了问题。ShowPosts 本身也在每次渲染时被重新创建,进一步加剧了问题。

有关更多详细信息,请参阅 你所认为的 React 函数组件一切都是错的

英文:

You should never put useEffect inside a function this way. You could perhaps wrap your function in useCallback, but useCallback needs to be on the outside. But you might be able to just have the useEffect do its work on the initial draw of the component based on its arguments and not worry about having a named ShowPosts function.

Your inline recipesDisplay variable will return a new value on every render, causing your component to rerender more than it needs to, probably constantly. And that will cause ShowPosts to constantly run. Assuming it even works with useEffect inside it, this will constantly be resetting your posts/recipes, exacerbating the problem. ShowPosts itself is also being recreated on every render, again adding to the problem.

See Everything you Thought You Knew About React Functional Components is Wrong for more details.

huangapple
  • 本文由 发表于 2023年6月1日 02:09:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76376254.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定