使用效果调用API几次Reactjs

发布于 2025-02-07 17:26:31 字数 565 浏览 3 评论 0原文

我在React组件中具有此使用效应函数。我在此处调用API VideGridState。 现在,这里发生的事情是在“伦理”页面上召集我的API 2倍,而计数发生变化时第二个。我希望当页面重新加载时将其称为单个时间。但是,当streamSearchText更改时,

  const [count, setCount] = useState(0);
  const [streamSearchText, setStreamSearchText] = useState("");
  useEffect(() => {
    videoGridState();
  }, [count]);

  useEffect(() => {
    const delayDebounceFn = setTimeout(() => {
      setCount(count + 1);
    }, 1000);

    return () => clearTimeout(delayDebounceFn);
  }, [streamSearchText]);

我该怎么做?

I have this useEffect function in react component. I am calling api videoGridState here.
Now what is happening here it is calling my api 2 times one at intitial page reaload and second one when count is changing. I want it to be called single time when page reloads. But also when streamSearchText changes

  const [count, setCount] = useState(0);
  const [streamSearchText, setStreamSearchText] = useState("");
  useEffect(() => {
    videoGridState();
  }, [count]);

  useEffect(() => {
    const delayDebounceFn = setTimeout(() => {
      setCount(count + 1);
    }, 1000);

    return () => clearTimeout(delayDebounceFn);
  }, [streamSearchText]);

How can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

睡美人的小仙女 2025-02-14 17:26:31

主要问题是您拥有两个 使用效果调用,因此它们每个都处理了,第二个触发了第一个(延迟之后),从而导致重复。

据我了解,您的目标是:

  1. 运行videigridState 立即在安装座上,并
  2. 时延迟1000ms后再次运行。

在每当streamSearchText更改转弯 令人惊讶的是尴尬。我可能最终会使用Ref:

const firstRef = useRef(true);
const [streamSearchText, setStreamSearchText] = useState("");
useEffect(() => {
    if (firstRef.current) {
        // Mount
        videoGridState();
        firstRef.current = false;
    } else {
        // `streamSearchText` change
        const timer = setTimeout(() => {
            videoGridState();
        }, 1000);
        return () => clearTimeout(timer);
    }
}, [streamSearchText]);

实时示例:

const { useState, useRef, useEffect } = React;

function videoGridState() {
    console.log("videoGridState ran");
}

const Example = () => {
    const firstRef = useRef(true);
    const [streamSearchText, setStreamSearchText] = useState("");
    useEffect(() => {
        if (firstRef.current) {
            // Mount
            videoGridState();
            firstRef.current = false;
        } else {
            // `streamSearchText` change
            const timer = setTimeout(() => {
                videoGridState();
            }, 1000);
            return () => clearTimeout(timer);
        }
    }, [streamSearchText]);

    return <div>
        <label>
            Search text:{" "}
            <input
                type="text"
                value={streamSearchText}
                onChange={(e) => setStreamSearchText(e.currentTarget.value)}
            />
        </label>
    </div>;
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

streamSearchText是>时,您也可以立即进行查询代码>“” ,而不仅仅是在安装上。这可能足够好,具体取决于您需要的严格程度。


另外,但是,如果您仍在看到两次“坐骑”上发生的事情,则可能会在应用程序周围使用react.strictmode运行库的开发副本(许多脚手架系统中的默认值)。请参阅此问题的答案.strictMode 可能会多次安装组件,并引起其他似乎令人惊讶的。

The main issue is that you have two useEffect calls, and so they're each handled, and the second triggers the first (after a delay), resulting in the duplication.

As I understand it, your goal is:

  1. Run videoGridState immediately on mount, and
  2. Run it again after a delay of 1000ms whenever streamSearchText changes

That turns out to be surprisingly awkward to do. I'd probably end up using a ref for it:

const firstRef = useRef(true);
const [streamSearchText, setStreamSearchText] = useState("");
useEffect(() => {
    if (firstRef.current) {
        // Mount
        videoGridState();
        firstRef.current = false;
    } else {
        // `streamSearchText` change
        const timer = setTimeout(() => {
            videoGridState();
        }, 1000);
        return () => clearTimeout(timer);
    }
}, [streamSearchText]);

Live Example:

const { useState, useRef, useEffect } = React;

function videoGridState() {
    console.log("videoGridState ran");
}

const Example = () => {
    const firstRef = useRef(true);
    const [streamSearchText, setStreamSearchText] = useState("");
    useEffect(() => {
        if (firstRef.current) {
            // Mount
            videoGridState();
            firstRef.current = false;
        } else {
            // `streamSearchText` change
            const timer = setTimeout(() => {
                videoGridState();
            }, 1000);
            return () => clearTimeout(timer);
        }
    }, [streamSearchText]);

    return <div>
        <label>
            Search text:{" "}
            <input
                type="text"
                value={streamSearchText}
                onChange={(e) => setStreamSearchText(e.currentTarget.value)}
            />
        </label>
    </div>;
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

You could also do the query immediately when streamSearchText is "", but that would happen every time streamSearchText was "", not just on mount. That may be good enough, depending on how rigorous you need to be.


Additionally, though, if you're still seeing something happen "on mount" twice, you may be running a development copy of the libraries with React.StrictMode around your app (the default in many scaffolding systems). See this question's answers for details on how React.StrictMode may mount your component more than once and throw in other seeming surprises.

热血少△年 2025-02-14 17:26:31

您的以下useseffect()函数使此行为实现:

  useEffect(() => {
    const delayDebounceFn = setTimeout(() => {
      setCount(count + 1);
    }, 1000);

    return () => clearTimeout(delayDebounceFn);
  }, [streamSearchText]);

因为它最初运行但称为setCount(),它更新了状态,并迫使组件重新渲染哪个依次运行第一个useeffect(),因为在依赖项数组中具有[count]

因此,[count]的周期继续

Your following useEffect() function makes this behaviour to happen:

  useEffect(() => {
    const delayDebounceFn = setTimeout(() => {
      setCount(count + 1);
    }, 1000);

    return () => clearTimeout(delayDebounceFn);
  }, [streamSearchText]);

Since it runs initially but called setCount() which updates the state, and forces a re-render of the component which in turn runs the first useEffect() since that has [count] in the dependency array.

And hence the cycle continues for the [count]

当梦初醒 2025-02-14 17:26:31
const Example = () => {

const { useState, useRef, useEffect } = React;

// Any async function or function that returns a promise
function myDownloadAsyncFunction(data) {
console.log("222222222222222222222")
  return new Promise((resolve) => setTimeout(resolve, 1000));
}

function DownloadButton() {
  const [queue, setQueue] = useState(Promise.resolve());

  onClickDownload = () => {
setQueue(queue
  .then(() => myDownloadAsyncFunction('My data'))
  .catch((err) => {console.error(err)})
)
  }

  return (
<button onClick={onClickDownload()}>Download</button>
  );
}
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

const Example = () => {

const { useState, useRef, useEffect } = React;

// Any async function or function that returns a promise
function myDownloadAsyncFunction(data) {
console.log("222222222222222222222")
  return new Promise((resolve) => setTimeout(resolve, 1000));
}

function DownloadButton() {
  const [queue, setQueue] = useState(Promise.resolve());

  onClickDownload = () => {
setQueue(queue
  .then(() => myDownloadAsyncFunction('My data'))
  .catch((err) => {console.error(err)})
)
  }

  return (
<button onClick={onClickDownload()}>Download</button>
  );
}
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文