onClick 时使用效果

edo*_*edo 0 reactjs react-hooks

我对如何将效果与应用程序逻辑一起使用感到困惑。

假设这个组件:

import React, { useEffect, useState } from "react";

export default function App() {
  const [query, setQuery] = useState('');

  useEffect( () => {
    fetch('https://www.google.com?q='+query)
    .then(response => console.log(response))
  }); // depends on what?

  return (
    <div>
      <input onChange={e => setQuery(e.target.value)} value={query} />
      <button>Ask Google about {query}</button>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

我要那个:

  • 当(且仅)用户单击按钮时,将使用输入的正确查询值运行提取
  • 如果提取仍在进行中并且用户单击,则会跳过提取但会触发效果(意思是:我故意不禁用该按钮,我希望运行效果函数,但我在该函数内部进行了检查,不要执行获取)。

问题:

  • 该效果不应在坐骑上触发(这没有任何意义)
  • 当查询更改时,效果不应触发,但如果我不将查询变量放入 useEffect 依赖项数组中,React 会抱怨(react-hooks/exhaustive-deps)
  • 当用户单击按钮时应触发该效果;我实现了这一点,例如使用 fake state isRun、 设置onClick={setIsRun(true)}、使效果取决于、在效果函数末尾[isRun]设置,并在效果函数的开头进行检查以防止从效果本身设置为 false 时由于状态改变而再次运行。这可行,但我发现它非常冗长且不舒服......setIsRun(false)if (!isRun)
  • 如果再次单击按钮(是否使用相同的query值)并且之前的获取尚未完成而不运行获取,则应该触发该效果:使用之前的解决方案,isRun它不会触发,因为isRun已经设置为1所以没有状态改变;也许在另一种状态下有一种方法,但同样非常冗长且违反直觉。
  • 最重要的是:代码应该干净且可读,而不使用“技巧”!

你会如何编写这样一个组件?

Dav*_*vid 7

听起来你useEffect根本不应该使用这个。您希望这种情况发生在用户操作上,而不是效果:

当(且仅)用户单击按钮时,将使用输入的正确查询值运行提取

删除useEffect并创建一个函数来处理点击:

const handleClick = (e) => {
    fetch('https://www.google.com?q='+e.target.value)
        .then(response => console.log(response));
};
Run Code Online (Sandbox Code Playgroud)

并将该函数传递给组件:

<button onClick={handleClick}>Ask Google about {query}</button>
Run Code Online (Sandbox Code Playgroud)

这里似乎令人困惑的是这些要求:

  • 如果提取仍在进行中并且用户单击,则将跳过提取但会触发效果
  • 如果再次单击按钮(无论是否使用相同的查询值)并且之前的提取尚未完成而不运行提取,则应触发该效果

该函数唯一做的就是执行一个fetch. 那么该手术是否应该进行呢?您提出的将状态保存在变量 ( isRun) 中以确定它是否应该发生的解决方案在这种情况下应该有效。我认为之前的问题是将它与useEffect你真正想要的只是一个函数混在一起。添加isRun到状态并在执行操作时相应地更新它:

const [isRun, setIsRun] = useState(false);

const handleClick = (e) => {
    if (isRun) { return; }
    setIsRun(true);
    fetch('https://www.google.com?q='+e.target.value)
        .then(response => {
            console.log(response);
            setIsRun(false);
        });
};
Run Code Online (Sandbox Code Playgroud)