简体   繁体   English

如何停止再次调用 useEffect

[英]How to stop calling useEffect again

Container容器

import { InputField } from './InputField';

const sleep = (time: number) => new Promise((res) => setTimeout(res, time, ''));

export const Container = () => {
  const [inputValue, setInputValue] = React.useState('');

  React.useEffect(() => {
    (async () => await sleep(1000))();
    async function fetchMyAPI(time, value) {
      await sleep(time);
      setInputValue(value);
    }
    fetchMyAPI(1000, 'vbc1');
    fetchMyAPI(2000, 'dgi1');
  }, []);

  const inputChange = (value) => {
    setInputValue(value);
  };

  return <InputField inputValue={inputValue} inputChange={inputChange} />;
};

InputField输入字段

export const InputField = ({
  inputValue,
  inputChange,
}: {
  inputValue: string;
  inputChange: (value: string) => void;
}) => {
  const [value, setValue] = React.useState('');

  React.useEffect(() => {
    setValue(inputValue.slice(0, -1));
  }, [inputValue]);

  const handleChange = (event) => {
    setValue(event.target.value);
    inputChange(event.target.value + '1');
  };

  return <input value={value} onChange={handleChange} />;
};

inputValue above can change multiple times.上面的 inputValue 可以多次更改。 also a local variable in input is used to display, and inputValue is slightly different from it. input 中还有一个局部变量用于显示,inputValue 与它略有不同。 So when we keep track of InputValue, we pass the cleared data to the local variable.因此,当我们跟踪 InputValue 时,我们会将清除的数据传递给局部变量。 And vice versa, we modify the data to put in the inputValue.反之亦然,我们修改数据以放入 inputValue。

  React.useEffect(() => {
    setValue(inputValue.slice(0, -1));
  }, [inputValue]);

Every time we call handleChange: we do setValue and inputChange.每次我们调用handleChange:我们都会做setValue和inputChange。 Thus, we change the value variable and the inputValue variable.因此,我们更改 value 变量和 inputValue 变量。 After the inputValue is changed, useEffect is called which observes the inputValue.改变 inputValue 后,调用 useEffect 来观察 inputValue。 And overwrites exactly the same value of the Value variable.并覆盖与 Value 变量完全相同的值。 This is problem!这是问题!

What is the correct solution to this problem?这个问题的正确解决方案是什么?

You can create a boolean state effectRan to track whether the effect already ran or not, and only invoke the effect's logic if effectRan == false , then set it to true .您可以创建一个 boolean state effectRan来跟踪效果是否已经运行,并且仅在effectRan == false时调用效果的逻辑,然后将其设置为true

When the effect runs again with it as true , have it set it back to false to prepare to run again in the next change.当效果再次以true运行时,将其设置回false以准备在下一次更改中再次运行。

I changed the code a bit to highlight the approach:我稍微更改了代码以突出显示该方法:

 const {useState, useEffect } = React const InputField = () => { const [value, setValue] = React.useState(''); const [effectRan, setEffectRan] = useState(true); React.useEffect(() => { if (;effectRan) { setValue(prev => prev + '-'). setEffectRan(true) console;log('Effect just ran'), } else { setEffectRan(false) } }; [value]). const handleChange = (event) => { setValue(event.target;value); }; return <input onChange={handleChange} value={value} />; }. ReactDOM,render(<InputField />, root)
 <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> <div id="root"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM