每当我输入内容时组件都会重新渲染,但我只想在按钮的 onClick 之后重新渲染

Posted

技术标签:

【中文标题】每当我输入内容时组件都会重新渲染,但我只想在按钮的 onClick 之后重新渲染【英文标题】:Components re-render whenever I type something but I want re-render only after onClick of button 【发布时间】:2021-10-16 16:04:06 【问题描述】:

目前,我正在开发一个 REACT 应用程序,它采用两个名称,给出一个百分比,然后根据该百分比显示一首诗。第一个提交收集信息并显示预期内容(百分比和诗歌)。不过在那之后,一旦我开始在输入字段中输入内容,LovePercentContent 和 LovePoem 就会继续重新渲染。注意:正在渲染的诗歌是从数组中随机挑选的。所以最大的问题是当你在输入字段中输入时,这首诗会不断更新。我对 React 还是很陌生,并通读了句柄事件文档。但我似乎仍然有问题。

https://reactjs.org/docs/handling-events.html

以下是我目前尝试过的。

应用程序的实时版本 https://love-poem-calculator.netlify.app/

import React,  useState  from "react";
import LovePercentContent from "../LovePercentContent/LovePercentContent";
import LovePoem from "../LovePoem/LovePoem";

const LovePercent = () => 
    const [yourName, setYourName] = useState("");
    const [yourCrushName, setYourCrushName] = useState("");
    const [yourLovePercent, setYourLovePercent] = useState("");
    const [yourLovePoems, setYourLovePoems] = useState("");
    const [yourSwitch, setYourSwitch] = useState(false);
    const [yourNameMissing, setYourNameMissing] = useState("");

    const handleSubmit = (e) => 
        e.preventDefault();
        if (yourName !== "" && yourCrushName !== "") 
            let calcQueryURL =
                "https://love-calculator.p.rapidapi.com/getPercentage?fname=" +
                yourName +
                "&sname=" +
                yourCrushName;
            console.log("yourName2", yourName);
            getLovePercent(calcQueryURL);
            setYourName("");
            setYourCrushName("");
         else 
            console.log("you most enter two names");
            setYourNameMissing("please enter both names");
        
    ;

    const getLovePercent = (url) => 
        fetch(url, 
            method: "GET",
            headers: 
                "x-rapidapi-key": process.env.REACT_APP_PERCENT_API_KEY,
                "x-rapidapi-host": "love-calculator.p.rapidapi.com",
            ,
        )
            .then((response) => response.json())
            .then((data) => 
                poemLines(data);
                return setYourLovePercent(data);
            )
            .catch((err) => 
                console.error(err);
            );
    ;

    function poemLines(data) 
        let percent = data.percentage;
        let url = `https://poetrydb.org/linecount/$percent`;
        fetch(url, 
            method: "GET",
        )
            .then((response) => response.json())
            .then((data) => 
                return setYourLovePoems(data);
            )
            .then(() => 
                return setYourSwitch(true);
            )
            .catch((err) => 
                console.error(err);
            );
    

    if (yourSwitch) 
        return (
            <>
                <h2>Enter Two Names:</h2>
                <input
                    name="yourName"
                    value=yourName
                    placeholder="Your Name"
                    onChange=(e) => setYourName(e.target.value)
                />
                <input
                    name="yourCrushName"
                    value=yourCrushName
                    placeholder="Your Crush's Name"
                    onChange=(e) => setYourCrushName(e.target.value)
                />
                <button type="submit" className="btn" onClick=handleSubmit>
                    Get Poem
                </button>
                <LovePercentContent data=yourLovePercent />
                <LovePoem data=yourLovePoems />
            </>
        );
    

    return (
        <>
            <h2>Enter Two Names:</h2>
            <input
                name="yourName"
                value=yourName
                placeholder="Your Name"
                onChange=(e) => setYourName(e.target.value)
            />
            <input
                name="yourName"
                value=yourCrushName
                placeholder="Your Crush's Name"
                onChange=(e) => setYourCrushName(e.target.value)
            />
            <button type="submit" className="btn" onClick=handleSubmit>
                Get Poem
            </button>
            yourNameMissing
        </>
    );
;

export default LovePercent;

【问题讨论】:

加载一段时间后出现什么错误? @SulemanAhmad 我没有收到错误消息。每次我在输入字段中输入时,这首诗都会不断重新渲染。我已经用更多信息更新了我原来的帖子。 因此您只想在单击按钮时获取诗歌。对吗? @SulemanAhmad 这正是我想要的。注意:感谢标题建议。 【参考方案1】:

你可以创建一个布尔状态

const [dataBool, setDataBool]=useState(false);

并在您单击按钮时通过创建函数或根据需要设置此true。之后在屏幕上显示poem data 时添加条件。如果这个布尔值为真,则返回诗歌,否则不返回。像这样:

   e.g. dataBool ? showPoems : notShowPoems

这样它只会在你点击它时显示。

【讨论】:

【参考方案2】:

我会说 Reactjs 的行为是正常的,你不应该太担心它


你所说的reloading实际上是re-rendering

每次状态变化(yourNameyourCrushName 在您的情况下)都会导致 Reactjs 重新渲染整个组件。

完全没问题,实际上 Reactjs 就是这样工作的

重渲染还不错,只有更新DOM是很有价值的,重渲染并不意味着DOM更新了,因为Reactjs应用了Virtual Dom机制

如果您不希望您的组件重新渲染,请考虑改用ref。

【讨论】:

感谢您的快速回复。唯一的问题是正在渲染的诗歌是从数组中随机挑选的。所以最大的问题是当你在输入字段中输入时,这首诗会不断更新。我会试试红色,看看情况如何。注意:我更新了我的帖子以添加到诗歌数组部分。

以上是关于每当我输入内容时组件都会重新渲染,但我只想在按钮的 onClick 之后重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

React Context API似乎重新渲染每个组件

React Context API 似乎要重新渲染每个组件

抑制触发的 Blazor 输入事件

刷新部分页面 (div)

Livewire 和 Flatpickr - 重新渲染后失败

vue和react中props变化后修改state的方式