React Custom Hook set 返回的函数不是函数

Posted

技术标签:

【中文标题】React Custom Hook set 返回的函数不是函数【英文标题】:React Custom Hook set function returned is not a function 【发布时间】:2020-08-23 11:27:10 【问题描述】:

因此,我构建了一个自定义挂钩来从 api 获取数据。代码如下:

export const useLambdaApi = () => 
  const [data, setData] = useState()
  const [isLoading, setIsLoading] = useState(false)

  useEffect(() => 
    const fetchData = async () =>  ... 
    fetchData();
  ,[isLoading]);

  return [data, setIsLoading];

在组件中我需要我做的数据:

export default function Comp (props) 
  const [data, setIsLoading] = useLambdaApi()

  useEffect(() => 
    const interval = setInterval(() => 
      setIsLoading(true)
      console.log(Date())
    , 10000);
    return () => 
      window.clearInterval(interval); // clear the interval in the cleanup function
    ;
  ,[data]);
  return( ... )

但我得到一个类型错误:TypeError: setIsLoading is not a function

我知道这一定很愚蠢,但我对 React 比较陌生,所以任何反馈都会有很大帮助。

谢谢。


编辑:

为了提供更多上下文,我在我的组件片段中添加了更多代码。我尝试从setInterval 更新isLoading 状态。但我也确实从 useEffect 尝试过,没有间隔,并且在 useEffect 之外......

这是堆栈跟踪:

PatientBoard.js:26 Uncaught TypeError: setIsLoading is not a function
    at PatientBoard.js:26
(anonymous) @ PatientBoard.js:26
setInterval (async)
(anonymous) @ PatientBoard.js:25
commitHookEffectList @ react-dom.development.js:21100
commitPassiveHookEffects @ react-dom.development.js:21133
callCallback @ react-dom.development.js:363
invokeGuardedCallbackDev @ react-dom.development.js:412
invokeGuardedCallback @ react-dom.development.js:466
flushPassiveEffectsImpl @ react-dom.development.js:24223
unstable_runWithPriority @ scheduler.development.js:676
runWithPriority$2 @ react-dom.development.js:11855
flushPassiveEffects @ react-dom.development.js:24194
(anonymous) @ react-dom.development.js:23755
scheduler_flushTaskAtPriority_Normal @ scheduler.development.js:451
flushTask @ scheduler.development.js:504
flushWork @ scheduler.development.js:637
performWorkUntilDeadline @ scheduler.development.js:238

【问题讨论】:

您的 sn-ps,尽管缺少一些细节,但对我来说似乎是合理的。除非您直接调用 setIsLoading 并将其放在处理程序中,否则它应该可以正常工作。您可以分享堆栈跟踪或更多详细信息吗? 感谢您的评论。我用堆栈跟踪和更多我从中调用函数的代码编辑了这个问题......计时器工作,状态data带有获取数据,尽管如果Iog从该组件data控制台将未定义。我认为是因为获取需要时间,但如果我在计时器中每 10 秒记录一次数据,它总是未定义,这也让我觉得很奇怪。 使用您的 sn-ps 我仍然无法重现错误:codesandbox.io/s/wizardly-sutherland-93msc - 可能是您有条件地使用了钩子或有其他导致问题的副作用。 感谢您抽出宝贵时间使用代码和框...但是,可能是什么原因导致此问题?我刚刚开始这个项目,所以它只是几个组件,这是唯一一个导入该自定义钩子的组件。 【参考方案1】:

像这样使用它:

更新:根据 URL 更改触发重新获取:

import React,  useEffect, useState  from "react";

// Passing URL as a parameter
export const useLambdaApi = (url) => 
  const [data, setData] = useState();
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => 
    const fetchData = async () => 
      const response = await fetch(url);
      const data = await response.json();

      // Set stats
      setIsLoading(false);
      setData(data);
    ;
    fetchData();

  // Passing URL as a dependency
  , [url]);

  // Return 'isLoading' not the 'setIsLoading' function
  return [data, isLoading];
;

// Using Hook into your component
export default function App() 
    // State will be changed if URL changes
    const [data, isLoading] = useLambdaApi('Your URL');

  // Loading indicator
  if (isLoading) return <div>Loading..</div>;

  // Return data when isLoading = false
  return (
    <div className="App">
      // Use data..
    </div>
  );

这是一个codesandbox 示例。

【讨论】:

是的,但除了使用isLoading 状态之外,我还希望能够从组件中更改它,从而触发另一个数据获取。这就是我传递 setIsLoading 函数的原因。但是,如果您可以推荐一种更好的方法来触发获取它也会有所帮助...我知道我的解决方案不是很优雅... 如果是这种情况,我建议将 url 作为参数传递,并在 useEffect 发生变化时进行观察。我会更新答案。 谢谢,我可以试试看效果如何。不过,我将不得不使用另一个参数,因为我的 API URL 不会更改……但是现在可以使用一个标志 @awran5 为什么建议避免返回除原始值之外的所有内容?返回任何你想要的东西是完全可行的,因为钩子只是函数。 @ChristianIvicevic 你说得对,对不起,这不是我想说的,可能会导致误解。

以上是关于React Custom Hook set 返回的函数不是函数的主要内容,如果未能解决你的问题,请参考以下文章

React在工作中对于 Custom React Hooks 一些思考

React在工作中对于 Custom React Hooks 一些思考

[React] Improve developer experience for accessing context with a custom React hook

[React Testing] Test your Custom Hook Module with react-hooks-testing-library

[NPM + React] Prepare a Custom React Hook to be Published as an npm Package

❤️ 在工作中对于 Custom React Hooks 一些思考